Open WangShuXian6 opened 5 months ago
watchEffect(async (onCleanup) => {
const { response, cancel } = doAsyncWork(id.value)
// `cancel` 会在 `id` 更改时调用
// 以便取消之前
// 未完成的请求
onCleanup(cancel)
data.value = await response
})
这段代码是一个 watchEffect
的使用示例,通常在 Vue.js 或类似的响应式框架中使用。watchEffect
用于创建一个副作用,它会自动追踪其依赖并在依赖改变时重新执行。让我们逐步分析并补全这段代码:
watchEffect 函数:
watchEffect
是用于自动监测其中包含的响应式引用(如 id.value
)的变化,并在变化时重新执行这个副作用函数。id.value
改变时,整个函数会重新执行。异步函数 doAsyncWork:
doAsyncWork
是一个异步函数,根据 id.value
进行某些异步操作(如 API 请求),并返回一个包含响应和取消函数的对象。response
是一个异步得到的响应。cancel
是一个函数,用于取消当前的异步操作。onCleanup 函数:
watchEffect
提供的一个函数,用于注册清理逻辑,这里的清理逻辑是调用 cancel
函数。watchEffect
的依赖发生变化并重新执行前,onCleanup
注册的函数会被调用,用于清理或取消之前的副作用。数据更新:
data.value = await response
用于更新某个响应式数据 data.value
,等待异步响应完成。为了完善这段代码,我们需要定义 doAsyncWork
函数,假设它是发起 HTTP 请求的函数。下面是如何实现它,包括取消逻辑:
async function doAsyncWork(id) {
let abortController = new AbortController();
try {
let response = await fetch(`https://api.example.com/data/${id}`, { signal: abortController.signal });
let data = await response.json();
return { response: data, cancel: () => abortController.abort() };
} catch (error) {
console.error('Request failed:', error);
return { response: null, cancel: () => {} };
}
}
结合 doAsyncWork
函数,以下是 Vue 组件中可能的实现:
import { watchEffect, ref } from 'vue';
export default {
setup() {
const id = ref(1);
const data = ref(null);
watchEffect(async (onCleanup) => {
const { response, cancel } = doAsyncWork(id.value);
onCleanup(cancel);
data.value = await response;
});
return {
id,
data
};
}
}
在这个例子中,每次 id
更改时,都会取消前一个请求(如果尚未完成),然后基于新的 id
发起新的请求。这样可以避免无效请求的累积和潜在的内存泄漏。
在 Vue.js 中,onCleanup
不是 watchEffect
的直接参数,而是在 watchEffect
函数的回调中提供的一个函数,用于注册清理逻辑。这个机制是为了管理副作用的生命周期,确保在副作用重新触发或组件销毁时能够进行适当的清理。
watchEffect 的作用:
watchEffect
用来自动追踪其函数体内部的响应式引用,并在这些响应式数据发生变化时重新执行。这种自动追踪使得 Vue 组件能够在数据更新时自动刷新相关的视图或执行相关的逻辑。
清理函数(onCleanup):
watchEffect
函数体内的代码重新执行前,如果之前的执行中注册了清理函数,Vue 将调用这些清理函数。这是通过 onCleanup
完成的。onCleanup
函数接收一个函数作为参数,该函数就是你希望在当前副作用停止之前执行的清理逻辑。watchEffect
中添加了事件监听器,使用 onCleanup
来移除监听器,防止内存泄露。watchEffect
中设置的定时器,可以在 onCleanup
中清除。以下是一个使用 onCleanup
来取消网络请求的例子:
import { watchEffect, ref } from 'vue';
export default {
setup() {
const id = ref(0);
const data = ref(null);
watchEffect((onCleanup) => {
const abortController = new AbortController();
fetch(`https://api.example.com/resource/${id.value}`, {
signal: abortController.signal
})
.then(response => response.json())
.then(json => {
data.value = json;
})
.catch(error => console.error('Fetch error:', error));
// 注册清理函数
onCleanup(() => {
abortController.abort();
});
});
return { id, data };
}
};
在这个例子中,每次 id
值变化时,前一个请求(如果尚未完成)将通过 abortController.abort()
被取消,避免不必要的网络请求和可能的状态冲突。这种模式对于确保资源得到正确管理和应用保持响应性非常重要。
src\components\Carousel.vue
<template> <view class="carousel-container"> <swiper :indicator-dots="true" :autoplay="true" :interval="3000" :duration="500" @change="onCarouselChange" <swiper-item v-for="(item, index) in images" :key="index" class="swiper-item" <view class="image-container"> <image :src="item.url" mode="aspectFill" class="image" /> </view> </swiper-item> </swiper> </view> </template>
>`src\components\useCarousel.ts`
```ts
import { ref } from 'vue';
export default function useCarousel() {
const current = ref(0);
const onCarouselChange = (event: any) => {
current.value = event.detail.current;
};
return {
current,
onCarouselChange,
};
}
使用组件
src\pages\tabbar\home.vue
<template> <view class="content"> <view class="carousel-container"> <image class="carousel-background" /> <view class="top-margin"></view> <carousel :images="images"></carousel> </view> </view> </template>
pnpm i --save-dev @types/node
tsconfig.json
添加 "types": ["node"]
{
"extends": "@vue/tsconfig/tsconfig.json",
"compilerOptions": {
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"lib": ["esnext", "dom"],
"types": ["@dcloudio/types","node"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
Vue3
VSCode 插件
Vue - Official 【原 volar】 https://marketplace.visualstudio.com/items?itemName=Vue.volar 禁止使用 vetur,已废弃。