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
将来的自己,会感谢现在不放弃的自己!