vue生命周期的理解
生命周期是什么?
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom -> 渲染、更新 -> 渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
生命周期 | 发生了什么 |
---|---|
beforeCreate | 初始化界面前 : 在当前阶段data、methods、computed以及watch上的数据和方法都不能被访问 |
created | 初始化界面后 : 在实例创建完成后发生,当前阶段已经完成了数据观测,也就是可以使用数据,更改数据,在这里更改数据不会触发updated函数,也就是不会更新视图,SSR可以放这里。 |
beforeMount | 挂载前 :完成模板编译,虚拟Dom已经创建完成,即将开始渲染。在此时也可以对数据进行更改,不会触发updated |
mounted | 挂在完成 : 将编译好的模板挂载到页面 (虚拟DOM挂载) ,可以在这进行异步请求以及DOM节点的访问,在vue用$ref操作 |
beforeUpdate | 更新数据前 : 组件数据更新之前调用,数据都是新的,页面上数据都是旧的 组件即将更新,准备渲染页面 , 可以在当前阶段进行更改数据,不会造成重渲染 |
updated | 组件更新后 : render重新渲染 , 此时数据和界面都是新的 ,要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新 |
beforeDestroy | 组件卸载前 : 实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,比如清除计时器 |
destroyed | 组件卸载后 : 组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁。 |
activited | keep-alive 专属 , 组件被激活时调用 |
deactivated | keep-alive 专属 , 组件被销毁时调用 |
实践:
beforeCreate() {
console.group("-----beforeCreate 创建前的状态-----");
console.log("%c%s", "color:red", `el : ${this.$el}`);
console.log("%c%s", "color:blue", this.$el);
console.log("%c%s", "color:red", `data : ${this.$data}`);
console.log("%c%s", "color:red", `message : ${this.messages}`);
},
...
如果在mouted以外的函数操作DOM就会报错(vue cli 创建的),如果是直接使用CDN方式在html文件中引入vue.js就不会报错,而且在beforeMount中可以得到渲染好的模板,因为得到的是一个el实例的对象引用。
验证数据更新,在beforeUpdate和Updated钩子函数里面都加上这样一段(CDN引入vue方式):
用vue-cli 生成的项目,引用的应该是运行时版本,所以,在beforeMount阶段,控制台打印不出el, 博主用到应该是src 引入的方式,所以在控制台中,beforeMount阶段也可以打印出el, 只是此时模板中的数据任然是未替换前的占位,我已经验证,总的来说,beforeMount阶段应该是虚拟DOM,到了mounted阶段才有真实的DOM
let text = document.getElementsByTagName('p')[0].textContent;
console.log(text)
然后触发函数更新:vm.message = '触发组件更新'
created钩子函数和beforeMount间的生命周期
el选项****如果有的话就继续向下编译,如果没有el选项**,则停止编译,也就意味着停止了生命周期,直到在该vue实例上调用vm.$mount(el)。此时注释掉代码中:
el: '#app',
然后运行可以看到到created的时候就停止了。
如果我们在后面继续调用vm.$mount(el),可以发现代码继续向下执行了。
var el = document.getElementById('app')
vm.$mount(el) //这个el参数就是挂在的dom接点
template参数选项的有无对生命周期的影响。
(1).如果vue实例对象中有template参数选项,则将其作为模板编译成render函数。
(2).如果没有template选项,则将外部HTML作为模板编译。
(3).可以看到template中的模板优先级要高于outer HTML的优先级。
这下就可以想想什么el的判断要在template之前了~是因为vue需要通过el找到对应的outer template。
在vue对象中还有一个render函数,它是以createElement作为参数,然后做渲染操作,而且我们可以直接嵌入JSX.
<div id="app">
<p>{{message}}</p>
</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'hello'
},
render(c){
return c('p',`this is contentElement ----${this.message}`)
},
template:`<p>这是template中的innerHTML 优先级高---{{message}}</p>`,
此时页面会得到:
所以综合排名优先级:
render函数选项 > template选项 > outer HTML.