
在 Vue 3 中,自定义 Hook 可以处理副作用(如订阅、定时器、异步请求等)。为了确保这些副作用在组件卸载或依赖变化时被正确清理,可以使用 onInvalidate
函数或手动清理逻辑。以下是如何在自定义 Hook 中清理副作用的详细步骤和示例:
1. 使用 watchEffect
的 onInvalidate
函数
watchEffect
提供了一个 onInvalidate
函数,用于在副作用失效时执行清理操作。onInvalidate
函数会在以下情况下被调用:
- 组件卸载时
- 依赖变化时
- 手动停止
watchEffect
时
import { ref, watchEffect } from 'vue';
export function useInterval(callback, delay) {
const intervalId = ref(null);
watchEffect((onInvalidate) => {
intervalId.value = setInterval(callback, delay);
onInvalidate(() => {
clearInterval(intervalId.value);
});
});
return intervalId;
}
2. 在组件中使用带清理的自定义 Hook
在组件中,你可以使用带清理的自定义 Hook。
<template>
<div>
<p>Count: {{ count }}</p>
</div>
</template>
<script>
import { ref } from 'vue';
import { useInterval } from './useInterval';
export default {
setup() {
const count = ref(0);
useInterval(() => {
count.value++;
}, 1000);
return {
count
};
}
};
</script>
3. 在 <script setup>
语法中使用带清理的自定义 Hook
在 <script setup>
语法中,使用带清理的自定义 Hook 也非常简洁。
<template>
<div>
<p>Count: {{ count }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useInterval } from './useInterval';
const count = ref(0);
useInterval(() => {
count.value++;
}, 1000);
</script>
4. 手动清理副作用
如果你不使用 watchEffect
,也可以手动清理副作用。通常,你可以在 onUnmounted
钩子中执行清理操作。
import { ref, onUnmounted } from 'vue';
export function useInterval(callback, delay) {
const intervalId = ref(null);
intervalId.value = setInterval(callback, delay);
onUnmounted(() => {
clearInterval(intervalId.value);
});
return intervalId;
}
5. 在组件中使用手动清理的自定义 Hook
在组件中,你可以使用手动清理的自定义 Hook。
<template>
<div>
<p>Count: {{ count }}</p>
</div>
</template>
<script>
import { ref } from 'vue';
import { useInterval } from './useInterval';
export default {
setup() {
const count = ref(0);
useInterval(() => {
count.value++;
}, 1000);
return {
count
};
}
};
</script>
6. 在 <script setup>
语法中使用手动清理的自定义 Hook
在 <script setup>
语法中,使用手动清理的自定义 Hook 也非常简洁。
<template>
<div>
<p>Count: {{ count }}</p>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { useInterval } from './useInterval';
const count = ref(0);
useInterval(() => {
count.value++;
}, 1000);
</script>
7. 处理异步请求的清理
对于异步请求,你可以使用 AbortController
来取消请求。
import { ref, watchEffect } from 'vue';
export function useFetch(url) {
const data = ref(null);
const error = ref(null);
const loading = ref(false);
watchEffect((onInvalidate) => {
const abortController = new AbortController();
async function fetchData() {
loading.value = true;
try {
const response = await fetch(url, { signal: abortController.signal });
if (!response.ok) {
throw new Error('Network response was not ok');
}
data.value = await response.json();
} catch (err) {
if (err.name !== 'AbortError') {
error.value = err;
}
} finally {
loading.value = false;
}
}
fetchData();
onInvalidate(() => {
abortController.abort();
});
});
return { data, error, loading };
}
8. 在组件中使用带清理的异步请求自定义 Hook
在组件中,你可以使用带清理的异步请求自定义 Hook。
<template>
<div>
<p v-if="loading">Loading...</p>
<p v-else-if="error">Error: {{ error.message }}</p>
<div v-else>
<p>Data: {{ data }}</p>
</div>
</div>
</template>
<script>
import { useFetch } from './useFetch';
export default {
setup() {
const { data, error, loading } = useFetch('https://api.example.com/data');
return {
data,
error,
loading
};
}
};
</script>
9. 在 <script setup>
语法中使用带清理的异步请求自定义 Hook
在 <script setup>
语法中,使用带清理的异步请求自定义 Hook 也非常简洁。
<template>
<div>
<p v-if="loading">Loading...</p>
<p v-else-if="error">Error: {{ error.message }}</p>
<div v-else>
<p>Data: {{ data }}</p>
</div>
</div>
</template>
<script setup>
import { useFetch } from './useFetch';
const { data, error, loading } = useFetch('https://api.example.com/data');
</script>
总结
- 在自定义 Hook 中,可以使用
watchEffect
的onInvalidate
函数来清理副作用。 - 如果不使用
watchEffect
,可以在onUnmounted
钩子中手动清理副作用。 - 对于异步请求,可以使用
AbortController
来取消请求。 - 在组件中,你可以像使用普通函数一样使用带清理的自定义 Hook,返回的响应式数据和方法可以直接在模板中使用。
- 在
<script setup>
语法中,使用带清理的自定义 Hook 更加简洁。
学在每日,进无止境!更多精彩内容请关注微信公众号。

原文出处:
内容由AI生成仅供参考,请勿使用于商业用途。如若转载请注明原文及出处。
出处地址:http://www.07sucai.com/tech/872.html
版权声明:本文来源地址若非本站均为转载,若侵害到您的权利,请及时联系我们,我们会在第一时间进行处理。