2

使用Vue-Query来获取数据

 4 weeks ago
source link: https://www.fly63.com/article/detial/12701
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用vue-Query来获取数据

构建现代大规模应用程序最具挑战性的方面之一是数据获取。加载和错误状态、分页、过滤、排序、缓存等功能会增加复杂性,并且经常会因大量样板代码而使应用程序变得臃肿。

vue query使用声明性语法处理和简化数据获取,并在幕后为我们处理所有这些重复性任务。

Vue-Query介绍

Vue-Query不能替代Axios或fetch。它是它们之上的抽象层。

  • 在后台更新过时的数据
  • 了解数据何时过期
  • 尽快反映数据更新
  • 将同一数据的多个请求合并为单个请求
  • 性能优化,例如分页和延迟加载
  • 管理服务器状态的内存和垃圾收集
  • 通过结构共享来记忆查询结果

Vue-Query向我们隐藏了所有这些复杂性。它是根据最佳实践进行默认配置的,同时也提供了一种在需要时更改此配置的方法。

在页面级别,我们需要获取所有产品,将它们显示在表格中,并使用一些简单的附加逻辑来选择其中一个。

<!-- 未使用vue query的组件 -->
<script setup>
import { ref } from "vue";
import BoringTable from "@/components/BoringTable.vue";
import ProductModal from "@/components/ProductModal.vue";

const data = ref();
const loading = ref(false);

async function fetchData() {
loading.value = true;
const response = await fetch(
`https://dummyjson.com/products?limit=10`
).then((res) => res.json());
data.value = response.products;
loading.value = false;
}

fetchData();

const selectedProduct = ref();

function onSelect(item) {
selectedProduct.value = item;
}
</script>

<template>
<div class="container">
<ProductModal
v-if="selectedProduct"
:product-id="selectedProduct.id"
@close="selectedProduct = null"
/>
<BoringTable :items="data" v-if="!loading" @select="onSelect" />
</div>
</template>

在选择产品的情况下,我们将显示一个弹窗并在显示加载状态时获取附加产品信息。

<!-- 未使用vue query的组件 -->
<script setup>
import { ref } from "vue";
import GridLoader from 'vue-spinner/src/GridLoader.vue'

const props = defineProps({
productId: {
type: String,
required: true,
},
});

const emit = defineEmits(["close"]);

const product = ref();
const loading = ref(false);

async function fetchProduct() {
loading.value = true;
const response = await fetch(
`https://dummyjson.com/products/${props.productId}`
).then((res) => res.json());
product.value = response;
loading.value = false;
}

fetchProduct();
</script>

<template>
<div class="modal">
<div class="modal__content" v-if="loading">
<GridLoader />
</div>
<div class="modal__content" v-else-if="product">
弹窗内容
</div>
</div>
<div class="modal-overlay" @click="emit('close')"></div>
</template>

添加Vue Query

该库预先配置了合理的默认值。这意味着对于基本用法我们不需要做太多事情。

<!-- 使用vue query的组件 -->
<script setup>
import { useQuery } from "vue-query";

function fetchData() {
// 获取数据
}

const { isLoading, data } = useQuery(
"uniqueKey",
fetchData
);
</script>

<template>
{{ isLoading }}
{{ data }}
</template>

在上面的例子中:

  • uniqueKey是用于缓存的唯一标识符
  • fetchData是一个通过 api 调用返回承诺的函数
  • isLoading指示 API 调用是否已完成
  • data是对 API 调用的响应

让我们将其合并到我们的示例中:

<!-- 未使用vue query的组件 -->
<script setup>
import { ref } from "vue";
import { useQuery } from "vue-query";

import BoringTable from "@/components/BoringTable.vue";
import OptimisedProductModal from "@/components/OptimisedProductModal.vue";

async function fetchData() {
return await fetch(`https://dummyjson.com/products?limit=10`).then((res) => res.json());
}

const { isLoading, data } = useQuery(
"products",
fetchData
);

const selectedProduct = ref();

function onSelect(item) {
selectedProduct.value = item;
}
</script>

<template>
<div class="container">
<OptimisedProductModal
v-if="selectedProduct"
:product-id="selectedProduct.id"
@close="selectedProduct = null"
/>
<BoringTable :items="data.products" v-if="!isLoading" @select="onSelect" />
</div>
</template>

由于加载状态由库处理,因此提取函数现在得到了简化。

这同样适用于弹窗组件:

<script setup>
import GridLoader from 'vue-spinner/src/GridLoader.vue'
import { useQuery } from "vue-query";

const props = defineProps({
productId: {
type: String,
required: true,
},
});

const emit = defineEmits(["close"]);

async function fetchProduct() {
return await fetch(
`https://dummyjson.com/products/${props.productId}`
).then((res) => res.json());
}

const { isLoading, data: product } = useQuery(
["product", props.productId],
fetchProduct
);

</script>

<template>
<div class="modal">
<div class="modal__content" v-if="isLoading">
<GridLoader />
</div>
<div class="modal__content" v-else-if="product">
弹窗内容
</div>
</div>
<div class="modal-overlay" @click="emit('close')"></div>
</template>

上面有两点需要注意:

  • useQuery返回带有名称的响应data,为了重命名它,我们可以使用像const { data: product } = useQuery(...)这样的 es6 解构,当在同一页面上执行多个查询时,这也很有用。
  • 简单的标识符字符串不起作用,因为所有产品都将使用相同的函数。我们还需要提供产品 ID["product", props.productId]

我们没有做太多事情,但我们得到了很多开箱即用的东西。首先,即使没有网络限制,重新访问产品时缓存的性能改进也是显而易见的。

  • 查询挂载的新实例
  • 窗口重新聚焦
  • 网络已重新连接。
  • 该查询可以选择配置重新获取间隔。

添加错误处理

到目前为止,我们的代码都默认 API 调用不会失败。但在实际应用中,情况并非总是如此。错误处理应该在 try-catch 块内实现,并且需要一些附加变量来处理错误状态。而Vue Query 通过提供isError变量提供了一种更直观处理错误的方式。

<script setup>
import { useQuery } from "vue-query";

function fetchData() {
// 获取数据
}

const { data, isError, error } = useQuery(
"uniqueKey",
fetchData
);
</script>

<template>
{{ data }}
<template v-if="isError">
An error has occurred: {{ error }}
</template>
</template>

Vue Query 通过用几行直观的代码逻辑替换复杂的样板代码来简化数据获取。这提高了可维护性并允许无缝连接新的服务器数据源。这样同样能使得应用程序速度更快、 响应更灵敏。

如果我们正在开发中型到大型应用程序,可以考虑将Vue Query添加到代码库中。

来自:https://blog.csdn.net/qq_42880714/article/details/132246907

链接: https://www.fly63.com/article/detial/12701


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK