有哪些生命周期方法
把所有生命周期打印一遍
import Vue from 'vue'
const app = new Vue({
// el: '#root',
template: '<div>{{text}}</div>',
data: {
text: 0
},
beforeCreate () {
console.log(this, 'breforeCreate')
},
created () {
console.log(this, 'created')
},
beforeMount () {
console.log(this, 'beforeMount')
},
mounted () {
console.log(this, 'mounted')
},
beforeUpdate () {
console.log(this, 'beforeUpdate')
},
updated () {
console.log(this, 'updated')
},
activated () {
console.log(this, 'activated')
},
deactivated () {
console.log(this, 'deactivated')
},
beforeDestroy () {
console.log(this, 'beforeDestroy')
},
destroyed () {
console.log(this, 'destroyed')
}
})
app.$mount('#root')
显示结果
结果依次显示 “breforeCreate” "created" "beforeMount" "mounted",说明在new Vue()时,这四个方法执行了。
breforeMount 和 mounted
如果把el:'#root'
注释掉,就只显示“breforeCreate” "created" ,因为mount的作用就是把vue组件生成的html内容,挂载到html节点上,所以当我们没有指定el:'#root'
或通过$mount
进行,是不会挂载到html节点上的。
breforeCreate 和 created
而 breforeCreate created 在初始化阶段就执行了。
beforeUpdate 和 updated
数据更新时,才会执行。
例如,每一秒钟更改数据,相应的每秒都会执行这两个生命周期
setInterval(() => {
app.text = app.text += 1
}, 1000)
beforeDestroy 和 destroyed
vue实例销毁时执行。
例如,设置一秒钟后销毁,控制台就会显示 "beforeDestroy" 和 "destroyed"
setTimeout(() => {
app.$destroy()
}, 1000)
activated 和 deactivated
和vue中一个原生的组件 keep-alive有关系。
分别打印出不同周期对应的$el
beforeCreate () {
console.log(this.$el, 'breforeCreate')
},
created () {
console.log(this.$el, 'created')
},
beforeMount () {
console.log(this.$el, 'beforeMount')
},
mounted () {
console.log(this.$el, 'mounted')
},
显示结果
undefined "beforeCreate"
undefined "created"
<div id="root"></div> "beforeMount"
<div>0</div> "mounted"
可以看到
beforeCreate 和 created 的 $el
是undefined,所以 beforeCreate 和 created 阶段是不能进行dom操作的,因为拿不到 dom 节点。
brforeMount 时,$el
变成了我们写在 html 中 div 节点。
mounted 时, $el
变成了 template 中的html,说明覆盖了html原来的 div 节点。
mounted之后,我们调用的所有生命周期方法,拿到的节点,都是渲染之后的节点。
所以一般
- 做 dom 相关操作会在 mounted 阶段
- 数据相关操作,可以在 created 或 mounted 阶段
生命周期的调用顺序
beforeCreate created beforeMount mounted 都是一次性的,组件只会调用一次。
beforeMount mounted 在服务端渲染,是不会被调用的,服务端渲染过程中,只会调用 beforeCreate created,因为 mount 是和 dom 操作相关的,服务端根本没有 dom 执行的环境, 所以不会有。
当数据发生变化时,beforeUpdate 和 updated 会调用。
当组件销毁时,beforeDestroy 和 destroyed 会调用。
声明周期中 VUE 实例有哪些区别
在不同的生命周期阶段,this.$el
是不同的,而在 mounted之后,一般不会改动 this.$el
,而是围绕阶段做某些操作,要尽量避免 this.$el
的变动,它会导致一些 vue 错误。
理解生命周期就是理解一张图
- init,new Vue() 先执行 init 操作,这个操作是默认执行的。
- init Events $ Lifecycle,调用 beforeCreate,所以此时,事件OK,但reactive不OK,所以这个阶段不要修改数据 data 中的数据。
- init injections $ reactivity,调用 created ,ajax请求获取数据赋值,最早在 created 阶段做。
- 判断 Has "el" option
- 如果有,执行下一步。
- 如果没有,等我们调用
vm.$mounted(el)
。
- 判断 Has "template" options
- 如果有,把 template 解析生一个 render 函数。render 函数会用 template 中的 html 去覆盖 html 中的 div 标签。在使用
.vue
文件进行开发的过程中,是没有 template 的,我们在.vue
文件中写的 template 都经过了 vue-loader 处理,直接变成了 render 函数,放在vue-loader 解析过的文件中;这样做的好处,把 template 解析成 render 函数,比较耗时,vue-loader 处理后,我们在页面上执行代码时,效率会变高。 - 如果没有,Compile el's outerHTML as template
- 如果有,把 template 解析生一个 render 函数。render 函数会用 template 中的 html 去覆盖 html 中的 div 标签。在使用
- 有了 render 函数之后
- beforeMount 执行
- 执行 render 函数
- Create vm.$el and replace "el" with it
- 执行 render 函数之后
- mounted 执行
- mounted之后,实例创建完成,后续过程,都是通过外部触发进行的。
- 当数据变化时
- beforeUpdate 执行
- Virtual DOM re-render and patch
- updated 执行
- 当组件销毁时
- beforeDestroy 执行
- Teardown watchers,child comonents and event listeners
- destroyed 执行
render 函数
直接使用 render 函数和使用 template 一样的。
import Vue from 'vue'
const app = new Vue({
// template: '<div>{{text}}</div>',
data: {
text: 0
},
render (h) {
return h('div', {}, this.text) // 参数1,创建的标签;参数2,对象配置;参数3,标签内容
},
})
app.$mount('#root')
render 函数执行时机
render (h) {
console.log('render function invoked')
return h('div', {}, this.text)
},
控制台结果
undefined "beforeCreate"
undefined "created"
<div id="root"></div> "beforeMount"
render function invoked
<div>0</div> "mounted"
在beforeMount 和 mounted 之间执行的
renderError 方法
renderError 方法,只有在开发时,才会被调用,正式打包上线时,不会被调用。帮助我们调试 render 中的错误。renderError 方法,只有在本组件 render 出现错误时,才会被调用;如果是子组件报错,是不会被捕获到的。
当 render 函数报错时,renderError 方法会执行。
render (h) {
throw new TypeError('render error')
// console.log('render function invoked')
// return h('div', {}, this.text)
},
renderError (h, err) {
return h('div', {}, err.stack)
}
errorCaptured 方法
可以用在正式开发环境中,帮助我们搜集线上的错误。如果在根组件使用这个方法,而根组件的子组件报的任何错误都可捕捉到,除非子组件把向上冒泡停止掉。
errorCaptured 方法使用与 renderError 相似,唯一的区别是:errorCaptured 会向上冒泡,并且正式环境可以使用。
总结
生命周期的执行顺序,调用时机,不同时机进行哪些操作,不同生命周期this.$el
的区别。