Vue 的生命周期 详细解析(使用场景等)
Vue生命周期图:
一、生命周期图的解读
new Vue():首先需要创建一个 Vue的实例对象
Init Events & Lifecycle :初始化:生命周期、事件(如:v-once),但数据代理还未开始(vm._data还未创建)
1、第一对:beforeCreate() 和 create()
(1)beforeCreate() : 无法通过vm访问到data中的数据、methods中的方法
Init injections & reactivity:初始化:数据监测、数据代理(监测数据变化,给对象中的属性配置getter\setter,对方法进行二次包装)
(2) created() : 可以通过vm访问到data中的数据、methods中配置的方法
Vue开始解析模板,生成虚拟DOM(内存中),页面还不能显示解析好的内容:Has "el" option? :是否有el配置项,如果有,跳到“Has template option?”,如果没有,当调用了vm.$mount(#root) 时,接着跳到“Has template option?”;是否有template选项,如果没有,以el的外标签html作为 模板(<div id="root"></div>);如果有,Compile template into render function ,将模板编译成渲染函数,替换掉html中的 <div id="root"></div>
2、第二对:beforeMount() 和 mount()
(1)beforeMount():页面呈现的是未经Vue 编译的DOM 结构;所有对DOM的操作,最终都不奏效
Create vm.$el and replace “el” with it :将内存中的 虚拟DOM转为真实DOM插入页面,vm.$el存放虚拟DOM ,el存放真实DOM(vm.$el instanceof HTMLElement 得出 true)
(2)mount():页面中呈现的是经过Vue编译的DOM;对DOM的操作均有效(尽可能避免操作DOM);至此初始化过程结束,一般在此进行:开启定时器、发送网络请求、订阅消息、绑定自定义事件等初始化操作
3、第三对:beforeUpdate() 和 update()
when data changes ,当data中的数据发生改变
(1)beforeUpdate():数据是新的,但页面是旧的,即:页面尚未和数据保持同步
Virtual DOM re-render and patch, 虚拟DOM和真实DOM做比较,并重新渲染DOM
(2)updated():数据是新的,页面也是新的,即:页面和数据保持同步
4、第4对:beforeDestroy() 和 destroy()when vm.$destroy() is called,当vm中的销毁方法被调用时,调用如下2个生命周期方法vm.$destroy() : 清理它与其他实例的连接,解绑它的全部指令及事件监听器(1)beforeDestroy():vm中所有的:data、methods、指令等都处于可用状态,马上要执行销毁过程,一般在此阶段:关闭定时器、取消订阅消息、解绑自定义事件等收尾操作。Teardown watchers,child components and event listeners, 移除所有监视 子组件 和事件监听器 (2)destroyed():收尾工作在 beforeDestroy方法中做了,destroy方法一般不做处理 其他:1、buforeCreate():数据监听和数据代理创建之前(_data 、getter和setter)2、比较重要的2个生命周期函数: mounted 和 beforedestroy(1)mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等(初始化操作)(2)beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等(收尾工作) 关于销毁Vue实例(1)销毁后,借助Vue开发者工具 看不到任何信息(2)销毁后自定义事件会失效,但原生DOM事件依然有效(3)一般不会再beforDestroy操作数据,因为即便操作数据,也不会再触发更新流程了。 教学视频:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=52&spm_id_from=pageDriver&vd_source=60a28e8364654bee938864b1d19905ec 第 49、50、51、52 集 练习:<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue 生命周期</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <h3 :style="{opacity}">欢迎学习Vue</h3> <h4 v-text="n"></h4> <h4>n:{{n}}</h4> <button @click="add">n++</button> <button @click="bye">销毁vm</button> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false; const vm = new Vue({ el:"#root", // template:` // <div> // <h3 :style="{opacity}">欢迎学习Vue</h3> // <h4>n:{{n}}</h4> // <button @click="n++">n++</button> // </div> // `, data:{ opacity:1, n:1 }, methods:{ add(){ console.log("add") this.n++ }, bye(){ console.log("bye") vm.$destroy(); } },watch:{ n(){ console.log("n变了") } }, beforeCreate(){ console.log("beforeCreate:"); console.log("this",this); debugger; //n 还没有进行数据代理 }, created(){ console.log("create"); //console.log("this:",this); //debugger; }, beforeMount(){ console.log("beforeMount"); // console.log("this:",this); // document.querySelector('h3').innerText = "哈哈1"; // debugger; }, mounted(){ this.timer=setInterval(()=>{ this.opacity -=0.01 if(this.opacity<=0) this.opacity=1 },1000) console.log("mounted"); // console.log("this:",this); // document.querySelector('h3').innerText = "哈哈2"; // debugger; }, beforeUpdate(){ console.log("mounted"); // console.log("this.n:",this.n) // debugger; }, updated(){ console.log("updated") // console.log("this.n:",this.n) // debugger; }, beforeDestroy(){ clearInterval(this.timer) console.log("beforeDestroy") console.log(this.n) this.add() console.log("n:",this.n) }, destroyed(){ console.log("destroy") } //Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕) // mounted(){ // setInterval(()=>{ // this.opacity -=0.01 // if(this.opacity<=0) this.opacity=1 // },16) // } }) </script> </html>