vue3认识组件与生命周期(小满zs vue3 笔记十二)
tip0: 调用用下面这两个钩子,收集依赖与触发依赖更新
// 依赖收集,用来调试用
onRenderTracked(e => {
console.log('------onRenderTracked--', e)
})
// 触发依赖,用来调试用
onRenderTriggered(e => {
console.log('------onRenderTriggered--', e)
})
tip: 1. 组件的认识
*组件基础
每一个.vue 文件呢都可以充当组件来使用,每一个组件都可以复用,

如下lifeCycle(或helloWorld)充当子组件

在引用时,只需要通过import引入,vue3 不需要注册组件,可以直接使用就可以如下:
<template>
<!-- 直接在这里使用,不需要通过components再启用-->
<life-cycle></life-cycle>
</template>
<script setup lang="ts">
import lifeCycle from './components/lifeCycle.vue';
</script>
组件生命周期
beforeCreate create setup 语法糖模式是没有这两个生命周期的,是这setup代替
简单来说就是一个组件从创建 到 销毁的 过程 成为生命周期
在我们使用Vue3 组合式API 是没有beforeCreate 和 created 这两个生命周期的,用setup代替
setup(代替vue2 beforeCreate->created)->beforeMount->mounted->beforeUpdate->updated->beforeUnmount->unmounted
onBeforeMount()
在组件DOM实际渲染安装之前调用。在这一步中,根元素还不存在。
onMounted()
在组件的第一次渲染后调用,该元素现在可用,允许直接DOM访问
onBeforeUpdate()
数据更新时调用,发生在虚拟 DOM 打补丁之前。
onUpdated()
DOM更新后,updated的方法即会调用。
onBeforeUnmount()
在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
onUnmounted()
卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。

源码:

在控制台看到的都是这些枚举值
export const enum LifecycleHooks {
BEFORE_CREATE = 'bc',
CREATED = 'c',
BEFORE_MOUNT = 'bm',
MOUNTED = 'm',
BEFORE_UPDATE = 'bu',
UPDATED = 'u',
BEFORE_UNMOUNT = 'bum',
UNMOUNTED = 'um',
DEACTIVATED = 'da',
ACTIVATED = 'a',
RENDER_TRIGGERED = 'rtg',
RENDER_TRACKED = 'rtc',
ERROR_CAPTURED = 'ec',
SERVER_PREFETCH = 'sp'
}
源码解析:
apiLifecycle.ts/render.ts
核心部分
// 创建hook做个缓存
export function injectHook(
type: LifecycleHooks,
hook: Function & { __weh?: Function },
target: ComponentInternalInstance | null = currentInstance,
prepend: boolean = false
): Function | undefined {
if (target) {
// 如果有hook函数直接返回否则创建一个空数组
const hooks = target[type] || (target[type] = [])
// cache the error handling wrapper for injected hooks so the same hook
// can be properly deduped by the scheduler. "__weh" stands for "with error
// handling".
const wrappedHook =
hook.__weh ||
(hook.__weh = (...args: unknown[]) => {
if (target.isUnmounted) {
return
}
// disable tracking inside all lifecycle hooks
// since they can potentially be called inside effects.
// 先停止收集避免重复收集依赖
pauseTracking()
// Set currentInstance during hook invocation.
// This assumes the hook does not synchronously trigger other hooks, which
// can only be false when the user does something really funky.
// 设置target为当前实例
setCurrentInstance(target)
const res = callWithAsyncErrorHandling(hook, target, type, args) // 执行完成钩子
unsetCurrentInstance() // 清空当前实例
resetTracking() // 恢复依赖收集
return res
})
if (prepend) {
hooks.unshift(wrappedHook)
} else {
hooks.push(wrappedHook)
}
return wrappedHook
} else if (__DEV__) {
const apiName = toHandlerKey(ErrorTypeStrings[type].replace(/ hook$/, ''))
warn(
`${apiName} is called when there is no active component instance to be ` +
`associated with. ` +
`Lifecycle injection APIs can only be used during execution of setup().` +
(__FEATURE_SUSPENSE__
? ` If you are using async setup(), make sure to register lifecycle ` +
`hooks before the first await statement.`
: ``)
)
}
}
// render.ts调用
componentUpdateFn 函数里用来更新
没有挂载创建并挂载
创建->render->patch->hook执行副作用函数->mounted
否则已经挂载了就更新
更新钩子-> 更新之前beforeUpdate -> render -> patch-> 执行更新hook副作用函数->updated
unmountComponent 销毁函数
执行函数beforeUnmount-> 卸载所有数据unmountChildren-> unmouted->卸载节点
测试代码如下:
<template>
<life-cycle v-if="lifeFlag"></life-cycle>
<button @click="lifeFlag = !lifeFlag">创建与销毁</button>
</template>
<script setup lang="ts">
import lifeCycle from './components/lifeCycle.vue';
import { ref } from 'vue'
const lifeFlag = ref<Boolean>(true)
</script>
生命周期组件:
<template>
<h3>我是组件</h3>
<div ref="div">{{ str }}</div>
<button @click="change">修改</button>
</template>
<script setup lang='ts'>
import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted,
onUnmounted, onUpdated, ref, onRenderTracked, onRenderTriggered } from 'vue';
// beforeCreate created setup语法糖是没有这两个函数的生命周期的
console.log('setup')
const str = ref<string>('组件')
const div = ref<HTMLDivElement>()
const change = () => {
console.log('修改组件了')
str.value = '修改组件了'
}
// 创建完成之前读不到dom
onBeforeMount(() => {
console.log('创建完成之前-onBeforeMount', div.value)
})
// 创建完成
onMounted(() => {
console.log('创建完成-onMounted', div.value)
})
// 更新组件之前
onBeforeUpdate(() => {
console.log('更新组件之前-onBeforeUpdate', div.value?.innerText)
})
// 更新
onUpdated(() => {
console.log('更新完成-onUpdated', div.value?.innerText)
})
// 销毁之前
onBeforeUnmount(() => {
console.log('销毁之前-onBeforeUnmount')
})
// 销毁完成
onUnmounted(() => {
console.log('销毁完成-onUnmounted')
})
// 依赖收集,用来调试用
onRenderTracked(e => {
console.log('------onRenderTracked--', e)
})
// 触发依赖,用来调试用
onRenderTriggered(e => {
console.log('------onRenderTriggered--', e)
})
</script>
引用文章: https://xiaoman.blog.csdn.net/article/details/122811060
将来的自己,会感谢现在不放弃的自己!

浙公网安备 33010602011771号