vue-24(组合式 API 中使用生命周期钩子)

发布于:2025-06-27 ⋅ 阅读:(17) ⋅ 点赞:(0)

在组合式 API 中使用生命周期钩子

生命周期钩子对于在不同阶段管理组件行为至关重要。在组合式 API 中,这些钩子的访问和使用方式与选项 API 不同。理解如何在 setup 函数中使用生命周期钩子对于有效管理组件状态、执行副作用和优化性能至关重要。本课将提供使用组合式 API 中生命周期钩子的全面指南,涵盖其目的、用法和实际示例。

理解组合式 API 中的生命周期钩子

在选项 API 中,像 mountedupdated 和 unmounted 这样的生命周期钩子被定义为组件对象中的选项。然而,在组合式 API 中,这些钩子被导入为函数并在 setup 函数中调用。这种方法允许更组织和可重用的代码,尤其是在与可组合项结合使用时。

Composition API 中可用的主要生命周期钩子是:

  • onBeforeMount: 在组件即将挂载时调用。
  • onMounted: 组件挂载完成后调用。
  • onBeforeUpdate: 组件即将更新其 DOM 之前调用。
  • onUpdated: 组件更新其 DOM 后调用。
  • onBeforeUnmount: 在组件实例卸载前立即被调用。
  • onUnmounted: 组件卸载后被调用。
  • onErrorCaptured: 当任何子组件的错误被捕获时被调用。
  • onRenderTracked: 组件渲染过程中被跟踪其响应式依赖时被调用。
  • onRenderTriggered: 当组件的响应式依赖项触发重新渲染时调用。
  • onActivated: 当组件作为缓存子树的一部分插入到 DOM 中时调用。主要用于与 <keep-alive> 一起使用。
  • onDeactivated: 当组件作为缓存子树的一部分从 DOM 中移除时调用。主要用于与 <keep-alive> 一起使用。

基本用法

要在 Composition API 中使用生命周期钩子,首先需要从 vue 中导入它。然后,在 setup 函数中调用钩子函数,传递一个回调函数,该函数将在对应的生命周期事件发生时执行。

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const message = ref('Hello, Composition API!');

    onMounted(() => {
      console.log('Component mounted!');
      // Perform any initialization tasks here
    });

    return {
      message
    };
  }
};
</script>

在这个例子中,onMounted 用于在组件挂载后向控制台记录一条消息。传递给 onMounted 的回调函数只会在初次渲染后执行一次。

示例:Mount获取数据

onMounted 的一个常见用例是在组件首次渲染时从 API 获取数据。

<template>
  <div>
    <p v-if="loading">Loading...</p>
    <ul v-else>
      <li v-for="todo in todos" :key="todo.id">{{ todo.title }}</li>
    </ul>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
  setup() {
    const todos = ref([]);
    const loading = ref(true);

    onMounted(async () => {
      try {
        const response = await fetch('https://jsonplaceholder.typicode.com/todos');
        todos.value = await response.json();
      } catch (error) {
        console.error('Error fetching data:', error);
      } finally {
        loading.value = false;
      }
    });

    return {
      todos,
      loading
    };
  }
};
</script>

在这个示例中,onMounted 用于从模拟 API 获取待办事项列表。loading ref 用于在数据获取过程中显示加载消息。一旦数据获取完成,todos ref 将被更新,加载消息将被隐藏。

示例:更新 DOM

onBeforeUpdate 和 onUpdated 可用于在组件的 DOM 更新前后执行任务。例如,你可能希望在更新前后测量元素的高度,以检测尺寸变化。

<template>
  <div>
    <p ref="messageRef">{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
import { ref, onBeforeUpdate, onUpdated } from 'vue';

export default {
  setup() {
    const message = ref('Initial Message');
    const messageRef = ref(null);

    onBeforeUpdate(() => {
      console.log('Before update:', messageRef.value?.offsetHeight);
    });

    onUpdated(() => {
      console.log('After update:', messageRef.value?.offsetHeight);
    });

    const updateMessage = () => {
      message.value = 'Updated Message';
    };

    return {
      message,
      messageRef,
      updateMessage
    };
  }
};
</script>

在这个例子中,onBeforeUpdate 在更新前记录了 messageRef 元素的身高,而 onUpdated 在更新后记录了身高。这可以用于检测由于更新导致元素尺寸的变化。

示例:清理资源

onBeforeUnmount 和 onUnmounted 用于在组件卸载前清理资源。这对于防止内存泄漏和确保应用程序正确运行非常重要。

<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
import { ref, onMounted, onBeforeUnmount } from 'vue';

export default {
  setup() {
    const message = ref('Hello, Composition API!');
    let intervalId = null;

    onMounted(() => {
      intervalId = setInterval(() => {
        console.log('Interval running');
      }, 1000);
    });

    onBeforeUnmount(() => {
      clearInterval(intervalId);
      console.log('Interval cleared');
    });

    return {
      message
    };
  }
};
</script>

在这个例子中,onMounted 用于启动一个间隔,每秒向控制台记录一条消息。onBeforeUnmount 用于在组件卸载前清除该间隔。这可以防止组件不再使用后间隔继续运行。

与 Composables 集成

生命周期钩子可以在 Composables 内部有效使用,以管理它们封装的逻辑的生命周期。这使您能够创建可重用的逻辑,该逻辑可以自动处理设置和清理。

// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue';

export function useMouse() {
  const x = ref(0);
  const y = ref(0);

  function update(event) {
    x.value = event.clientX;
    y.value = event.clientY;
  }

  onMounted(() => {
    window.addEventListener('mousemove', update);
  });

  onUnmounted(() => {
    window.removeEventListener('mousemove', update);
  });

  return { x, y };
}
<template>
  <div>
    <p>Mouse position: x={{ x }}, y={{ y }}</p>
  </div>
</template>

<script>
import { useMouse } from './useMouse';

export default {
  setup() {
    const { x, y } = useMouse();

    return { x, y };
  }
};
</script>

在这个例子中,useMouse 组合封装了跟踪鼠标位置的逻辑。onMounted 用于在组合首次使用时添加事件监听器,而 onUnmounted 用于在组合不再使用时移除事件监听器。

高级生命周期钩子使用

onErrorCaptured

onErrorCaptured 钩子允许你处理子组件中发生的错误。这可以用于记录错误、显示错误消息或防止应用程序崩溃。

<template>
  <div>
    <p>Parent Component</p>
    <ChildComponent />
  </div>
</template>

<script>
import { onErrorCaptured } from 'vue';
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  setup() {
    onErrorCaptured((err, instance, info) => {
      console.error('Error captured:', err);
      console.log('Component instance:', instance);
      console.log('Error info:', info);
      // Handle the error here
      return false; // Prevents the error from propagating further
    });

    return {};
  }
};
</script>
// ChildComponent.vue
<template>
  <div>
    <button @click="generateError">Generate Error</button>
  </div>
</template>

<script>
export default {
  setup() {
    const generateError = () => {
      throw new Error('This is a test error');
    };

    return {
      generateError
    };
  }
};
</script>

在这个例子中,父组件中的 onErrorCaptured 钩子捕获了子组件抛出的错误。该钩子将错误记录到控制台,并阻止其进一步传播。

onRenderTracked 和 onRenderTriggered

这些钩子对于调试应用程序中的性能问题很有用。onRenderTracked 在组件的响应式依赖在渲染过程中被跟踪时被调用,而 onRenderTriggered 在响应式依赖触发重新渲染时被调用。

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="updateMessage">Update Message</button>
  </div>
</template>

<script>
import { ref, onRenderTracked, onRenderTriggered } from 'vue';

export default {
  setup() {
    const message = ref('Initial Message');

    onRenderTracked((event) => {
      console.log('Dependency tracked:', event);
    });

    onRenderTriggered((event) => {
      console.log('Re-render triggered by:', event);
    });

    const updateMessage = () => {
      message.value = 'Updated Message';
    };

    return {
      message,
      updateMessage
    };
  }
};
</script>

在这个例子中,onRenderTracked 记录渲染过程中被追踪的依赖,而 onRenderTriggered 记录触发重新渲染的依赖。这可以帮助你识别不必要的重新渲染,并优化组件的性能。

onActivated 和 onDeactivated

这些钩子与 <keep-alive> 组件一起使用,用于管理缓存组件的生命周期。onActivated 在组件作为缓存子树的一部分插入到 DOM 中时被调用,而 onDeactivated 在组件作为缓存子树的一部分从 DOM 中移除时被调用。

<template>
  <keep-alive>
    <component :is="activeComponent" />
  </keep-alive>
  <button @click="toggleComponent">Toggle Component</button>
</template>

<script>
import { ref } from 'vue';
import ComponentA from './ComponentA.vue';
import ComponentB from './ComponentB.vue';

export default {
  components: {
    ComponentA,
    ComponentB
  },
  setup() {
    const activeComponent = ref('ComponentA');

    const toggleComponent = () => {
      activeComponent.value = activeComponent.value === 'ComponentA' ? 'ComponentB' : 'ComponentA';
    };

    return {
      activeComponent,
      toggleComponent
    };
  }
};
</script>
// ComponentA.vue
<template>
  <div>
    <p>Component A</p>
  </div>
</template>

<script>
import { onActivated, onDeactivated } from 'vue';

export default {
  setup() {
    onActivated(() => {
      console.log('Component A activated');
    });

    onDeactivated(() => {
      console.log('Component A deactivated');
    });

    return {};
  }
};
</script>

在这个例子中,<keep-alive> 组件缓存了当前组件。当切换当前组件时,会在被停用的组件上调用 onDeactivated,在激活的组件上调用 onActivated


网站公告

今日签到

点亮在社区的每一天
去签到