Vue生命周期自己的理解 + 别人的解释

168 阅读2分钟

Vue的生命周期

官方文档的图 图1 image.png

图2:没必要理解这个??emm,感觉学习起来难度很大,很想就是先学概念再有案例,不来得更舒服么??

image.png

写成自己理解就是

1、new一个Vue实例的时候,触发Init(Events & Lifecycle是他的方法??),

2、然后这时候,就会触发beforeCreated生命周期,这时候触发Init(injections & reactivity???),

3、再然后,会触发created生命周期了,走入了判断是否有el option的分支,

no-> (when vm.$mounted(el) is called??又是啥玩意??
大概率vm.mounte(el)就是所谓的挂载到Vue实例的方法),即把el挂载上去),
true->进入判断template option的分支

4、再然后进入判断template option的分支

true->编译render函数
false->不会编译outerHTML 作为这个叫 template的模板?

5、这时候就触发 beforeMount生命周期了,这个我看得懂,$el应该是挂载上去vue实例了

6、挂载实例后,开始触发mounted生命周期,mounted生命周期,这里面就引入了一个叫虚拟dom的玩意?那beforeUpdate和updated生命周期,就是基于(虚拟dom re-render and patch??这个又是啥???)

7、when vm.destroy()这个钩子函数触发了,beforeDestroy生命周期开始触发,这时候,开始卸货了,监听者,儿子节点??是挂载到最大的el节点下的子节点??(我也不理解这个childcomponents,还有eventlisteners(vondestroy() 这个钩子函数触发了,`beforeDestroy生命周期开始触发`,这时候,开始卸货了, 监听者,儿子节点??是挂载到最大的el节点下的子节点??(我也不理解这个child components),还有 event listeners(即v-on emit() 这些指令开始卸载了),window相关的api 可以在这里用

 // 清楚滚动事件
 window.onscroll = null
 // 清除定时器
 window.clearInterval(this.timer)
 // 删除全局变量 释放内存
 // 手动垃圾回收
 window.aname = null

8、最后卸载完了,就会触发 Destroyed生命周期,(如果我的想法的话,这个可以去通知其他组件,告诉他们我卸载了??谁知道呢??哈哈)

别人的解释:

  1. beforeCreate:在实例初始化之后,数据观测 (Data Observer) 和 event/watcher 事件配置之前被调用。
  2. created:在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer)、属性和方法的运算,watch/event 事件回调;然而,挂载阶段还没开始,$el 属性目前不可见。
  3. beforeMount:在挂载开始之前被调用,相关的 render 函数首次被调用。
  4. mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。

如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内(PS:注意 mounted 不会承诺所有的子组件也都一起被挂载。

如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted:

  1. beforeUpdate:数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
  2. updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以现在可以执行依赖于 DOM 的操作,然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之(PS:计算属性与 watcher 会在后面的篇幅中进行介绍)。
  3. beforeDestroy:实例销毁之前调用,在这一步,实例仍然完全可用。
  4. destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

具体案例

  <div id="demo">
    </div>
    <script src="vue.js"></script>
    <script>
        var vm = new Vue({
            // 选项
            el: '#demo',
            data: {
                // name: 'yao'
                num: 1
            },
            // template: `
            //     <div>
            //         {{name}}
            //     </div>
            // `,
            render(h) {
                console.log('--------------render---------------')
                let virtualdom = h('div', null, this.num)
                // 虚拟DOM对象,是该函数接受新的Model之后执行得到的对象
                console.log(virtualdom)
                return virtualdom
            },
            // 创建前 没M没有V(虚拟DOM真实DOM)
            beforeCreate() {
                console.log('--------------beforeCreate---------------')
                console.log('View', this.$el)
                console.log('Model', this.$data)
            },
            // 创建后 修改数据一般发生created里面 ajax在这里触发,因为这里是最早拿到数据
            created() {
                console.log('--------------created---------------')
                console.log('View', this.$el)
                console.log('Model', this.$data)
            },
            // 挂载前 没M没有V(虚拟DOM真实DOM) 读取了模板,但是没更新上去,编译模板
            beforeMount() {
                console.log('--------------beforeMount---------------')
                console.log('View', this.$el)
                console.log('Model', this.$data)
            },
            // 挂载后 V和M都更新完毕 V已经完全更新了,所以一般把DOM的操作放在这里
            mounted() {
                console.log('--------------mounted---------------')
                console.log('View', this.$el)
                console.log('Model', this.$data)

                this.$nextTick(() => {
                    //    vm._data.name = vm._data.name++
                })
                setInterval(()=>{
                    var num = this.num
                    this.num = ++num
                    console.log(this)
                },1000)
                // debugger
            },
            // 更新前
            beforeUpdate() {
                console.log('--------------beforeUpdate---------------')

                console.log('View', this.$el.outerHTML)
                console.log('Model', this.$data)
            },
            // 更新后
            updated() {
                console.log('--------------updated---------------')

                console.log('View', this.$el.outerHTML)
                console.log('Model', this.$data)
            }
        })

        // vm._data.name = '2' // 改变data里面的dom的时候,会触发 update生命周期
        // vm.$el.innerHTML = 3 //如果使用$el去操作dom改变他得值的话,那么是不会触发生命周期的
    </script>

如图例所示的结果

image.png