1 引出生命周期 生命周期
又名生命周期回调函数 、生命周期函数、生命周期钩子
是什么:Vue 在关键时刻帮我们调用的一些特殊名称的函数
生命周期函数的名字不可更改 ,但函数的具体内容是程序员根据需求编写的
生命周期函数中的 this
指向是 vm
或 组件实例对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 <div id ="root" > <h2 v-if ="a" > 你好啊</h2 > <h2 :style ="{opacity}" > 看笔记学Vue</h2 > </div > <script type ="text/javascript" > Vue.config.productionTip = false ; new Vue({ el: '#root' , data: { a: false , opacity: 1 }, methods: { }, mounted() { console .log('mounted' , this ); setInterval(() => { this .opacity -= 0.01 ; if (this .opacity <= 0 ) this .opacity = 1 }, 16) }, }) </script >
2 分析生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 <title > 分析生命周期</title > <script type ="text/javascript" src ="../js/vue.js" > </script > <div id ="root" :x ="n" > <h2 v-text ="n" > </h2 > <h2 > 当前的n值是:{{ n }}</h2 > <button @click ="add" > 点我n+1</button > <button @click ="bye" > 点我销毁vm</button > </div > <script type ="text/javascript" > Vue.config.productionTip = false ; new Vue({ el: '#root' , // <h2 > 当前的n值是: {{n}} </h2 > // <button @click ="add" > 点我n+1</button > data: { n: 1 }, methods: { add() { console .log('add' ); this .n++ }, bye() { console .log('bye' ); this .$destroy() } }, watch: { n() { console .log('n变了' ) } }, beforeCreate() {console .log('beforeCreate' )}, created() {console .log('created' )}, beforeMount() {console .log('beforeMount' )}, mounted() {console .log('mounted' )}, beforeUpdate() {console .log('beforeUpdate' )}, updated() {console .log('updated' )}, beforeDestroy() {console .log('beforeDestroy' )}, destroyed() {console .log('destroyed' )}, })</script >
先看一下图中间大框框的内容
先判断有没有 el
这个配置项,没有就调用 vm.$mount(el)
,如果两个都没有就一直卡着,显示的界面就是最原始的容器的界面。有el
这个配置项,就进行判断有没有template
这个配置项,没有 template
就将el
绑定的容器编译为 vue
模板,来个对比图。
template 的作用
第一种情况,有 template: 如果 el 绑定的容器没有任何内容,就一个空壳子,但在 Vue 实例中写了 template,就会编译解析这个 template 里的内容,生成虚拟 DOM,最后将 虚拟 DOM 转为 真实 DOM 插入页面(其实就可以理解为 template 替代了 el 绑定的容器的内容)。
第二种情况,没有 template: 没有 template,就编译解析 el 绑定的容器,生成虚拟 DOM,后面就顺着生命周期执行下去。
3 总结生命周期
beforeCreate(创建前) :数据监测(getter和setter)和初始化事件还未开始,此时 data 的响应式追踪、event/watcher 都还没有被设置,也就是说不能访问到data、computed、watch、methods上的方法和数据。
created(创建后) :实例创建完成,实例上配置的 options 包括 data、computed、watch、methods 等都配置完成,但是此时渲染得节点还未挂载到 DOM,所以不能访问到 $el
属性。
beforeMount(挂载前) :在挂载开始之前被调用,相关的render函数首次被调用。此阶段Vue开始解析模板,生成虚拟DOM存在内存中,还没有把虚拟DOM转换成真实DOM,插入页面中。所以网页不能显示解析好的内容。
mounted(挂载后) :在el被新创建的 vm.$el(就是真实DOM的拷贝)替换,并挂载到实例上去之后调用(将内存中的虚拟DOM转为真实DOM,真实DOM插入页面)。此时页面中呈现的是经过Vue编译的DOM,这时在这个钩子函数中对DOM的操作可以有效,但要尽量避免。一般在这个阶段进行:开启定时器,发送网络请求,订阅消息,绑定自定义事件等等
beforeUpdate(更新前) :响应式数据更新时调用,此时虽然响应式数据更新了,但是对应的真实 DOM 还没有被渲染(数据是新的,但页面是旧的,页面和数据没保持同步)。
updated(更新后) :在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。此时 DOM 已经根据响应式数据的变化更新了。调用时,组件 DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前) :实例销毁之前调用。这一步,实例仍然完全可用,this
仍能获取到实例。在这个阶段一般进行关闭定时器,取消订阅消息,解绑自定义事件。
destroyed(销毁后) :实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务端渲染期间不被调用。
常用的生命周期钩子
mounted 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
beforeDestroy 清除定时器、解绑自定义事件、取消订阅消息等收尾工作
关于销毁Vue 实例
销毁后借助Vue开发者工具看不到任何信息
销毁后自定义事件会失效,但原生DOM事件依然有效
一般不会在beforeDestroy
操作数据,因为即便操作数据,也不会再触发更新流程了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <div id ="root" > <h2 :style ="{opacity}" > 欢迎学习Vue</h2 > <button @click ="opacity = 1" > 透明度设置为1</button > <button @click ="stop" > 点我停止变换</button > </div > <script type ="text/javascript" > Vue.config.productionTip = false ; new Vue({ el: '#root' , data: { opacity: 1 }, methods: { stop() { this .$destroy() } }, mounted() { console .log('mounted' , this ); this .timer = setInterval(() => { console .log('setInterval' ); this .opacity -= 0.01 ; if (this .opacity <= 0 ) this .opacity = 1 }, 16) }, beforeDestroy() { clearInterval(this .timer); console .log('vm即将驾鹤西游了' ) }, })</script >