- vue3 生命周期详细
- 在 Vue 3 中,生命周期钩子是组件在其生命周期的不同阶段可以运行的函数。这些钩子提供了一个方式,允许你在组件创建、更新、销毁等关键时刻执行代码。Vue 3 的生命周期钩子与 Vue 2 相比有一些变化,主要是因为 Vue 3 使用了 Composition API。以下是 Vue 3 中可用的主要生命周期钩子:
- setup()
- 这不是传统意义上的生命周期钩子,但它是 Composition API 的入口点。
- 它在组件实例被创建和生命周期钩子之前被调用。
- 这是定义响应式变量和函数的地方。
- onBeforeMount()
- 在挂载(即将把模板编译成 DOM)开始之前调用。
- onMounted()
- 在组件挂载到 DOM 上后调用。
- 这是执行如访问或操作 DOM 的任务的好时机。
- onBeforeUpdate()
- 在响应式数据变化并且 DOM 重新渲染之前调用。
- onUpdated()
- 在响应式数据变化导致的虚拟 DOM 重新渲染和打补丁之后调用。
- 用于执行依赖于组件已更新的 DOM 的操作。
- onBeforeUnmount()
- 在卸载组件实例之前调用。
- onUnmounted()
- 在组件实例被卸载后调用。
- onActivated() 和 onDeactivated()
- 这些钩子在使用
<keep-alive>
缓存组件时使用。 onActivated
在组件被激活时调用。onDeactivated
在组件被停用时调用。
- onErrorCaptured() 和 onRenderTracked() 和 onRenderTriggered()
onErrorCaptured
用于捕获子组件抛出的异常。onRenderTracked
和onRenderTriggered
用于调试,它们提供了有关渲染过程的信息。
这些生命周期钩子可以在 Composition API 的 setup()
函数内部使用,你可以直接导入它们,例如:
javascript
import { onMounted, onUpdated } from 'vue';
export default {
setup() {
onMounted(() => {
console.log('组件已挂载');
});
onUpdated(() => {
console.log('组件已更新');
});
// ...
}
}
记住,Vue 3 的 Composition API 引入了更灵活的组织组件逻辑的方式,允许你更好地重用和管理代码。
- 在 Vue 3 中,
<script setup>
是一种新的组件写法,专为 Composition API 设计。这种语法简化了组件的编写方式,使得代码更简洁且易于阅读。以下是<script setup>
标签的主要特点和使用方式:
基本使用
- 直接声明式语法
- 使用
<script setup>
标记的脚本自动将顶层的绑定视为组件的定义,无需定义export default
。 - 在这个脚本中定义的变量、函数等将自动可用于模板中。
vue
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<button @click="count++">Count is: {{ count }}</button>
</template>
高级特性
- 使用 Props 和 Emits
- 可以使用
defineProps
和defineEmits
在<script setup>
中声明组件的 props 和 emits。
vue
<script setup>
const props = defineProps(['title', 'likes']);
const emit = defineEmits(['update']);
</script>
- 使用组件
- 在
<script setup>
中导入的组件可以直接在模板中使用,无需在components
选项中注册。
vue
<script setup>
import UserCard from './UserCard.vue';
</script>
<template>
<UserCard />
</template>
- 使用计算属性和侦听器
- 可以直接使用
computed
和watch
。
vue
<script setup>
import { computed, watch, ref } from 'vue';
const count = ref(0);
const doubled = computed(() => count.value * 2);
watch(count, (newValue, oldValue) => {
console.log(`count changed from ${oldValue} to ${newValue}`);
});
</script>
- 使用生命周期钩子
- 生命周期钩子可以直接导入并使用。
vue
<script setup>
import { onMounted } from 'vue';
onMounted(() => {
console.log('组件已挂载');
});
</script>
使用 <script setup>
的好处
- 简洁性 :减少了模板和脚本之间的样板代码。
- 作用域清晰 :顶层绑定自动成为模板的一部分,易于理解组件的结构。
- 更好的 TypeScript 集成 :提供了更自然的方式在 Vue 中使用 TypeScript。
注意事项
<script setup>
是 Vue 3.0 的新增特性,因此确保你的项目使用的是 Vue 3.0 或更高版本。- 使用
<script setup>
时,组件的定义方式与标准的<script>
有所不同。你需要熟悉 Composition API 的基本概念才能充分利用这种语法。
总的来说,<script setup>
提供了一种更简洁、更高效的方式来编写 Vue 组件,特别是当与 Composition API 结合使用时。
defineExpose
- 在 Vue 3 的
<script setup>
语法中,defineExpose
是一个特殊的编译宏,用于显式地暴露组件的公共实例属性。当你使用<script setup>
编写组件时,默认情况下,模板外部无法访问组件的内部状态。这意味着,如果你需要在父组件中或者通过模板引用 (ref
) 访问子组件的属性、方法或者其他响应式状态,你需要使用defineExpose
来暴露这些属性。
使用 defineExpose
基本语法如下:
vue
<script setup>
import { ref } from 'vue';
const internalState = ref('secret');
// 暴露给外部的方法和属性
defineExpose({
internalState,
exposedMethod() {
console.log('这是一个暴露的方法');
}
});
</script>
在上面的例子中,internalState
和 exposedMethod
被暴露出去,这意味着它们可以从组件的外部访问,例如:
vue
<template>
<ChildComponent ref="child" />
</template>
<script setup>
import { ref, onMounted } from 'vue';
import ChildComponent from './ChildComponent.vue';
const child = ref(null);
onMounted(() => {
console.log(child.value.internalState); // 访问子组件的状态
child.value.exposedMethod(); // 调用子组件的方法
});
</script>
注意事项
- 有选择性地暴露 :只有通过
defineExpose
显式暴露的属性和方法才可以从外部访问。这有助于保持组件的封装性,避免无意间暴露内部状态。 - 主要用途 :
defineExpose
主要用于需要通过父组件或模板引用访问子组件的情况。 - ** 结合使用** :通常与模板中的
ref
指令结合使用,允许父组件直接访问子组件的实例。 - 谨慎使用 :过度使用
defineExpose
可能破坏组件的封装性和独立性,应谨慎使用。
defineExpose
提供了一种在 <script setup>
语法中控制组件暴露行为的简洁方式,有助于维护组件之间的清晰界限。
getCurrentInstance
- 在 Vue 3 中,
getCurrentInstance
是一个用于获取当前组件实例的方法。它通常在 Composition API 的上下文中使用,特别是在<script setup>
或其他 Composition API 函数中。通过getCurrentInstance
,你可以访问组件的内部状态、生命周期钩子、props、slots、emit 等,尽管这种做法通常不推荐,因为它破坏了组件的封装性和可测试性。
使用 getCurrentInstance
你可以在组件的 setup 函数中使用 getCurrentInstance
来获取当前组件实例的引用。例如:
javascript
<script setup>
import { getCurrentInstance, onMounted } from 'vue';
const instance = getCurrentInstance();
onMounted(() => {
if (instance) {
console.log(instance.props); // 访问 props
console.log(instance.emit); // 访问 emit 方法
// ... 更多操作
}
});
</script>
注意事项
- 封装性 :直接使用
getCurrentInstance
可能会破坏组件的封装性。它允许你访问组件的内部状态,这可能会导致难以维护和测试的代码。 - 用途 :
getCurrentInstance
主要用于那些无法通过正常的 Composition API 解决的特殊情况。它可能在库或高级功能的开发中更常见。 - 返回值 :
getCurrentInstance
返回一个包含组件实例的对象,或者如果在组件上下文之外调用,则返回null
。 - 谨慎使用 :鉴于
getCurrentInstance
提供对组件内部的广泛访问,建议谨慎使用此功能。在大多数情况下,标准的 Composition API 提供的功能已经足够。
总之,getCurrentInstance
是一个强大的函数,它提供了对 Vue 组件实例的直接访问。然而,应谨慎使用它,避免过度依赖于组件的内部实现细节。
defineEmits
- 在 Vue 3 中,
defineEmits
是一个专门用于 Composition API 的编译宏,它用于声明组件发出的自定义事件。在<script setup>
语法中,使用defineEmits
可以定义一个组件可以触发的事件,从而使得父组件能够监听这些事件。这是一种在组件间通信的方式,类似于在传统的 Options API 中使用this.$emit
。
基本用法
- 声明事件
- 在
<script setup>
中,使用defineEmits
声明组件将触发的事件。
vue
<script setup>
const emit = defineEmits(['update', 'submit']);
</script>
- 触发事件
- 使用
emit
函数触发事件,并传递所需的参数。
vue
<script setup>
const emit = defineEmits(['update']);
function handleClick() {
emit('update', 'newValue');
}
</script>
<template>
<button @click="handleClick">Update</button>
</template>
使用带有验证的 Emit
- 你还可以提供一个带有验证的对象,来确保发出的事件符合预期的格式。
vue
<script setup>
const emit = defineEmits({
update: (payload) => {
// 进行验证
return typeof payload === 'string';
}
});
</script>
注意事项
- 组件间通信 :
defineEmits
是组件间通信的一部分,特别是当子组件需要通知父组件某些动作发生时。 - 类型安全 :如果你在使用 TypeScript,
defineEmits
还可以提供类型检查,增加代码的健壮性。 - 与传统 API 的区别 :在 Vue 3 的 Composition API 中,
defineEmits
取代了 Vue 2 中的this.$emit
方法。它与<script setup>
语法密切相关,提供了更简洁的事件声明方式。 - 事件命名 :建议使用小写或 kebab-case(短横线分隔)命名事件,以保持与 HTML 属性的一致性。
使用 defineEmits
可以使得组件的事件更加明确和可管理,同时提供了更好的类型检查和验证功能。这样,组件的使用者可以清楚地知道组件能够发出哪些事件,以及这些事件携带的数据类型。
withDefaults
- 在 Vue 3 的
<script setup>
语法中,withDefaults
是一个编译宏,用于为组件的props
提供默认值。当你使用defineProps
在<script setup>
中声明组件的props
时,withDefaults
可以帮助你为这些props
设置默认值。
使用 withDefaults
- 基本语法
- 首先,使用
defineProps
声明组件的props
。 - 然后,使用
withDefaults
将默认值应用于这些props
。
vue
<script setup>
const props = withDefaults(defineProps({
title: String,
likes: Number
}), {
title: '默认标题',
likes: 0
});
</script>
<template>
<h1>{{ title }}</h1>
<p>Likes: {{ likes }}</p>
</template>
在上面的例子中,title
prop 如果没有提供值,将默认为 '默认标题'
,likes
prop 将默认为 0
。
注意事项
- 类型安全 :在使用 TypeScript 时,
withDefaults
可以帮助确保 prop 的类型安全性,同时提供默认值。 - 清晰的默认值声明 :通过
withDefaults
,组件的使用者可以更清楚地看到每个 prop 的默认值,这有助于理解组件的预期行为。 - 与 Vue 2 的区别 :在 Vue 2 中,你可以在
props
定义中直接指定默认值。在 Vue 3 的<script setup>
语法中,由于defineProps
是一个编译时宏,不支持在其内部直接指定默认值,因此需要withDefaults
来实现这一功能。
使用 withDefaults
为 props
设置默认值是 Vue 3 <script setup>
语法的一个优雅特性,它使得组件的 prop 定义更加清晰和易于管理。