Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册js方法,可以让我们用自己注册的js方法控制整个大局,在这些事件响应方法中的this直接指向的是vue的实例。
特别值得注意的是created钩子函数和mounted钩子函数的区别
beforeCreate
在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
created
实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
beforeMount
在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。
beforeUpdate
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
该钩子在服务器端渲染期间不被调用。
beforeDestroy
实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。
created钩子函数和beforeMount间的生命周期
对于created钩子函数和beforeMount间可能会让人感到有些迷惑,下面我就来解释一下:el选项的有无对生命周期过程的影响
首先系统会判断对象中有没有el选项有el选项,则继续编译过程没有el选项,则停止编译,也意味着暂时停止了生命周期,直到vm.$mount(el)下面我展示一下:new Vue({ el: '#app', beforeCreate: function () { console.log('调用了beforeCreat钩子函数') }, created: function () { console.log('调用了created钩子函数') }, beforeMount: function () { console.log('调用了beforeMount钩子函数') }, mounted: function () { console.log('调用了mounted钩子函数') } })
demo如下:可以看到,在el选项填写且正确的时候,生命周期将正常进行而当我们把el去掉:new Vue({ beforeCreate: function () { console.log('调用了beforeCreat钩子函数') }, created: function () { console.log('调用了created钩子函数') }, beforeMount: function () { console.log('调用了beforeMount钩子函数') }, mounted: function () { console.log('调用了mounted钩子函数') } })
demo:可以看到,生命周期的钩子函数执行到created就结束了而当我们不加el选项,但是手动执行vm.$mount(el)方法的话,也能够使暂停的生命周期进行下去,例如:var vm = new Vue({ beforeCreate: function () { console.log('调用了beforeCreat钩子函数') }, created: function () { console.log('调用了created钩子函数') }, beforeMount: function () { console.log('调用了beforeMount钩子函数') }, mounted: function () { console.log('调用了mounted钩子函数') } }) vm.$mount('#app')
demo如下,可以看到,这个时候虽然对象中没有el参数,但通过$mount(el)动态添加的方式,也能够使生命周期顺利进行template参数选项的有无对生命周期的影响
1.如果Vue实例对象中有template参数选项,则将其作为模板编译成render函数2.如果没有template参数选项,则将外部的HTML作为模板编译(template),也就是说,template参数选项的优先级要比外部的HTML高3.如果1,2条件都不具备,则报错我们可以把模板写在template参数选项中:new Vue({ el: '#app', template: '' }) demo:模板在templated参数中找到了哟~
也可以把参数选项写在外部HTML中,像这样:外部HTML:创建对象实例: new Vue({ el: '#app' })模板是在外部HTML中找到的~
demo:那么有趣的问题来了,当模板同时放在template参数选项和外部HTML中,会怎样呢?例如:外部HTML:模板是在外部HTML中找到的~
创建Vue实例(包含template参数选项)new Vue({ el: '#app', template: '' })模板在templated参数中找到了哟~
demo如下:很显然,正如我上面下的结论一样,最终显示的是“模板在templated参数中找到了哟~”而不是“模板是在外部HTML中找到的~”,因为template参数的优先级比外部HTML的优先级要高【注意】1.为什么判断el要发生在判断template前面呢因为Vue需要通过el的“选择器”找到对应的template。总结一下上述的过程,Vue通过el参数去找到对应的template。然后,根据el参数给出的“选择器”,首先去Vue实例对象本身的template选项参数中找,如果没有template参数,则到外部HTML中寻找,找到后将模板编译成render函数2.实际上,在Vue中,有render函数这个选项,它以createElement作为参数,做渲染操作。当然你也可以不调用createElement,而直接嵌入JSX(学习react的同学对此应该很熟悉吧)。new Vue({ el: '#demo', render (createElement) { return (....) } })
【注意】render选项参数比template更接近Vue解析器!所以综合排列如下:render函数选项 > template参数 > 外部HTMLVue的编译过程——把模板编译成 render 函数
Vue的编译实际上是指Vue把模板编译成 render 函数的过程我们可以通过Vue.compile这个实时编译模板的函数来看一看:用官方文档的例子做个解释:I'm a template!
{{ message }}
No message.
会被渲染成function anonymous() { with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No message.")])])} }
beforeMount和mounted钩子函数间的生命周期
对于这一点,我也感到有些迷惑,百度后之后也没什么头绪,最后我思考的结果是这样的:正因为render函数和template选项的“优先级”比外部HTML要高,所以,最后一般会存在一个外部HTML模板被Vue实例本身配置的模板所“替代”的过程也就是上图所说的 “replace”
(如果大家有不同意见也可以在评论处一起讨论)beforeUpdate钩子函数和updated钩子函数间的生命周期
在Vue中,数据更改会导致虚拟 DOM 重新渲染,并先后调用beforeUpdate钩子函数和updated钩子函数但要注意一点:重渲染(调用这两个钩子函数)的前提是被更改的数据已经被写入模板中!!(这点很重要)例如:var vm = new Vue({ el: '#app', data: { number: 1 }, template: '', beforeUpdate: function () { console.log('调用了beforeUpdate钩子函数') }, updated: function () { console.log('调用了updated钩子函数') } }) vm.number = 2
控制台上并没有如我们预料那样输出调用两个钩子函数的文本而当我们改成var vm = new Vue({ el: '#app', data: { number: 1 }, // 在模板中使用number这个数据 template: '', beforeUpdate: function () { console.log('调用了beforeUpdate钩子函数') }, updated: function () { console.log('调用了updated钩子函数') } }) vm.number = 2{{ number }}
这个时候,调用两个钩子函数的文本就被输出来了总之,只有Vue实例中的数据被“写入”到我们的模板中,它的改变才可以被Vue追踪,重渲染从而调用 beforeUpdate钩子函数和updated钩子函数beforeDestroy和destroyed钩子函数间的生命周期
beforeDestroy钩子函数在实例销毁之前调用。在这一步,实例仍然完全可用。destroyed钩子函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。【注意】就如同调用在Vue实例上调用$mounted会使暂停的生命周期继续一样,调用$destroy()会直接销毁实例