vue生命周期

vue生命周期

个人公众号地址

vue2.x 选项式 API(Options API)

1、前置:

eg:

export default {
    name: "DevPoint",
    data() {
        return { num: "123", };
        },
    mounted() {}
    };

代码的过程:

  Vue.prototype._init = function (options?: Object) {
    const vm: Component = this
    ......
    vm._self = vm

    // 初始化生命周期(找到第一个非抽象父级,将当前实例添加到父实例的 $children 属性里,并设置当前实例的 $parent 为父实例,在当前实例上设置一些属性)
    initLifecycle(vm)

    // 初始化事件中心(主要调用updateComponentListeners,主要作用就是将绑定在组件上的事件,保存至vm._events属性中)
    initEvents(vm)

    // 初始化渲染(主要定义了vm的_c和$createElement方法)
    initRender(vm)
    callHook(vm, 'beforeCreate')

    // 初始化注入
    initInjections(vm) // resolve injections before data/props

    // 初始化状态
    // 初始化 props、data、methods、watch、computed 等属性
    initState(vm)

    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')
    ......
  }
}


响应式流程:

  • 在init的时候会利用Object.defineProperty方法(不兼容 IE8)监听Vue实例的响应式数据的变化从而实现数据劫持能力(利用了 JavaScript 对象的访问器属性get和set,在 Vue3 中会使用 ES6 的Proxy来优化响应式原理)。在初始化流程中的编译阶段,当render function被渲染的时候,会读取Vue实例中和视图相关的响应式数据,此时会触发getter函数进行依赖收集(将观察者Watcher对象存放到当前闭包的订阅者Dep的subs中),此时的数据劫持功能和观察者模式就实现了一个 MVVM 模式中的 Binder,之后就是正常的渲染和更新流程。
  • 当数据发生变化或者视图导致的数据发生了变化时,会触发数据劫持的setter函数,setter会通知初始化依赖收集中的Dep中的和视图相应的Watcher,告知需要重新渲染视图,Wather就会再次通过update方法来更新视图

2、生命周期钩子

生命周期过程 组件状态 使用场景
new Vue()、New Component Detected()
init Event & Lifecycle 初始化生命周期、初始化事件中心、初始化渲染
1、beforeCreat() 实例初始化之后,this 指向创建的实例,不能访问到 data、computed、watch、methods 上的方法和数据。
如果 data() 在这个钩子里面更新,一旦选项式 API(Options API)加载完,更新将会将会丢失数据。
它对于调用不操作组件数据的 API 非常有用,常用于初始化非响应式变量。
init injections & reactivity 、选项 API 加载 data 数据注入、
data 数据劫持:
(1、递归遍历 data 选项,添加 setter/getter;
2、把劫持过的变量都放在组件实例 this、vm 上)
2、created() 实例创建完成,可访问 data、computed、watch、methods 上的方法和数据。
未挂载到 DOM不能访问到$el 属性; $ref 属性内容为空数组
常用于简单的 ajax 请求如果请求信息过多,页面会长时间处于白屏状态),页面的初始、开启 websorcket 长连接化
编译模板(如果 App 是用 ' npm run build ' 构建的,这步可能已经完成了) 1、vue 会判断这个组件有没有 el 挂载点,有就接着判断有没有视图模板 template,如果有,万事大吉,render function 顺利开始;
2、如果没有 el 挂载点,那么得开始创建了;
3、如果没有 template,那就把 el 的 outerHTML 当作 template。
3、beforeMount() 模板已编译,因此它存储在内存中,但尚未附加到页面,尚未创建任何 DOM 元素,因此 $el 在这个阶段仍然不可用
渲染组件(创建 DOM 节点) 1、根据 render()渲染函数,生成"抽象语法树 AST" ,再把 AST 第一次被创建成“虚拟 DOM(VNode)” (Vnode 是真实 DOM 的一种数据描述,它本质上是 json 格式的数组)
2、根据 Vnode 创建真实 DOM。把声明式变量都替换成真实数据,DOM 渲染完成。|
4、mounted() 组件已安装并显示在页面上, $el 可被正常使用,在此阶段可以从 Vue 访问和操作 DOM 开定时器、做请求、获取 VNode 信息和操作
组件安装——>进入更新阶段
5、beforeUpdate() 使用这个钩子来访问 DOM 的当前状态,甚至可以更新 data() 。
更新数据 1、当 vue 上下文中的 data 发生变化时,使用 render()渲染函数再生成一个新的 Vnode。
2、使用 Diff 运算,patch('old vnode','new vnode')找出两个 Vnode 之间最小差异。
3、notify 通过 Watcher 根据“依赖收集”再次更新真实 DOM。
【虚拟 DOM 存在的价值:大大地降低了“jQuery 时代下人为寻找 DOM 变化差异”的不足,最小化地去更新 DOM(尽可能地减少了 DOM 操作)。所以虚拟 DOM 是 MVVM 的本质。】
6、updated() 访问$el DOM 内容或其他任何有关 DOM 内容的内容,它将显示新的、重新渲染后的版本 大部分时候 watch 选项的功能就满足需求。
避免在这个钩子函数中操作数据,可能陷入死循环
组件进入销毁阶段 调用$destroy()或路由切换
7、beforeDestory() 此事件仍然可以访问 DOM 元素以及与组件有关的任何其他内容。 1. 清除自己定义的定时器
2. 解除事件绑定 scroll
3. 当前页面使用了$on 需要销毁前解绑
组件卸载 1、拆卸掉 watcher,所以 DOM 不可能再发生更新。
2、拆卸掉当前组件的所有子组件,所以这些子组件也进入销毁阶段。
3、卸载掉当前组件中的事件处理器。
8、destroyed() 仍然可以访问访问 this.$el,以及 data() 、methods 和 watch。

3、父子组件生命周期

3.1、加载渲染过程(当子组件完成挂载后,父组件会主动执行一次 beforeUpdate/updated 钩子函数(仅首次))

父 beforeCreate->父 created->父 beforeMount->子 beforeCreate->子 created->子 beforeMount- >子 mounted->父 mounted (首次:->父 beforeUpdate -> 父 updated)

3.2、子组件更新过程

父 beforeUpdate->子 beforeUpdate->子 updated->父 updated

3.3、父组件更新过程

父 beforeUpdate -> 父 updated

3.4、销毁过程

父 beforeDestroy->子 beforeDestroy->子 destroyed->父 destroyed

vue3.x 组合式 API(Composition API)

1、钩子函数的变化

created() 和 beforeCreated() ——> setup()
beforeMount() ——> onBeforeMount()
mounted() ——> onMounted()
beforeUpdate() ——> onBeforeUpdate()
updated() ——> onUpdated()
beforeUnmount() ——> onBeforeUnmount()
unmounted() ——> onUnmounted()

2、用法:在 setup() 函数中定义挂钩

<script>
export default {
    setup() {
        // 所有钩子逻辑
        onBeforeMount(() => {
            //  beforeMount() 逻辑
        });
        ...
    },
};
</script>

或者

<script setup>
// 所有钩子的逻辑代码在这里
</script>
posted @ 2022-06-25 15:42  樛了个elevens  阅读(47)  评论(0编辑  收藏  举报