微信公众号
扫描关注微信公众号
博客大厅

如何在自定义 Hook 中清理副作用?

原创 来源:博客站 阅读 0 03月23日 07:56 听全文

在 Vue 3 中,自定义 Hook 可以处理副作用(如订阅、定时器、异步请求等)。为了确保这些副作用在组件卸载或依赖变化时被正确清理,可以使用 onInvalidate 函数或手动清理逻辑。以下是如何在自定义 Hook 中清理副作用的详细步骤和示例:

1. 使用 watchEffectonInvalidate 函数

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 中,可以使用 watchEffectonInvalidate 函数来清理副作用。
  • 如果不使用 watchEffect,可以在 onUnmounted 钩子中手动清理副作用。
  • 对于异步请求,可以使用 AbortController 来取消请求。
  • 在组件中,你可以像使用普通函数一样使用带清理的自定义 Hook,返回的响应式数据和方法可以直接在模板中使用。
  • <script setup> 语法中,使用带清理的自定义 Hook 更加简洁。
学在每日,进无止境!更多精彩内容请关注微信公众号。
原文出处: 内容由AI生成仅供参考,请勿使用于商业用途。如若转载请注明原文及出处。
出处地址:http://www.07sucai.com/tech/872.html
版权声明:本文来源地址若非本站均为转载,若侵害到您的权利,请及时联系我们,我们会在第一时间进行处理。
轻松 一刻
>