返回列表 发帖

接收响应式状态 {#accepting-reactive-state}

useFetch() 接收一个静态 URL 字符串作为输入——因此它只会执行一次 fetch 并且就此结束。如果我们想要在 URL 改变时重新 fetch 呢?为了实现这一点,我们需要将响应式状态传入组合式函数,并让它基于传入的状态来创建执行操作的侦听器。

举例来说,useFetch() 应该能够接收一个 ref:

const url = ref('/initial-url')
const { data, error } = useFetch(url)
// 这将会重新触发 fetch
url.value = '/new-url'
或者接收一个 getter 函数:

// 当 props.id 改变时重新 fetch
const { data, error } = useFetch(() => `/posts/${props.id}`)
我们可以用 watchEffect() 和 toValue() API 来重构我们现有的实现:

```js{8,13} // fetch.js import { ref, watchEffect, toValue } from 'vue'

export function useFetch(url) { const data = ref(null) const error = ref(null)

watchEffect(() => { // 在 fetch 之前重置状态 data.value = null error.value = null // toValue() 将可能的 ref 或 getter 解包 fetch(toValue(url)) .then((res) => res.json()) .then((json) => (data.value = json)) .catch((err) => (error.value = err)) })

return { data, error } }

`toValue()` 是一个在 3.3 版本中新增的 API。它的设计目的是将 ref 或 getter 规范化为值。如果参数是 ref,它会返回 ref 的值;如果参数是函数,它会调用函数并返回其返回值。否则,它会原样返回参数。它的工作方式类似于 [`unref()`](/api/reactivity-utilities.html#unref),但对函数有特殊处理。
注意 `toValue(url)` 是在 `watchEffect` 回调函数的**内部**调用的。这确保了在 `toValue()` 规范化期间访问的任何响应式依赖项都会被侦听器跟踪。
这个版本的 `useFetch()` 现在能接收静态 URL 字符串、ref 和 getter,使其更加灵活。watch effect 会立即运行,并且会跟踪 `toValue(url)` 期间访问的任何依赖项。如果没有跟踪到依赖项(例如 url 已经是字符串),则 effect 只会运行一次;否则,它将在跟踪到的任何依赖项更改时重新运行。
这是[更新后的 `useFetch()`](https://play.vuejs.org/#eNptVMFu ... QlREeecnP8DWEwr0Q==),为了便于演示,添加了人为延迟和随机错误。
## 约定和最佳实践 {#conventions-and-best-practices}
### 命名 {#naming}
组合式函数约定用驼峰命名法命名,并以“use”作为开头。
### 输入参数 {#input-arguments}
即便不依赖于 ref 或 getter 的响应性,组合式函数也可以接收它们作为参数。如果你正在编写一个可能被其他开发者使用的组合式函数,最好处理一下输入参数是 ref 或 getter 而非原始值的情况。可以利用 [`toValue()`](/api/reactivity-utilities#tovalue) 工具函数来实现:
```js
import { toValue } from 'vue'
function useFeature(maybeRefOrGetter) {
  // 如果 maybeRefOrGetter 是一个 ref 或 getter,
  // 将返回它的规范化值。
  // 否则原样返回。
  const value = toValue(maybeRefOrGetter)
}
如果你的组合式函数在输入参数是 ref 或 getter 的情况下创建了响应式 effect,为了让它能够被正确追踪,请确保要么使用 watch() 显式地监视 ref 或 getter,要么在 watchEffect() 中调用 toValue()。

前面讨论过的 useFetch() 实现提供了一个接受 ref、getter 或普通值作为输入参数的组合式函数的具体示例。

返回列表