组件相关钩子函数: beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destoryed
还有两个特殊的(使用keep-alive):activated、deactivated(不详述)
v2.5.0+新增: errorCaptured (暂时还不知道咋用)html
路由守卫:
全局&路由独享:beforeEach、beforeResolve(v2.5.0+新增)、afterEach ;beforeEnter(路由独享,相似beforeEach)
组件内:beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeavevue
实例初始化以后git
this指向建立的实例
数据观测(data observer)和event/watcher配置还没有完成
不能访问到methods、data、computed、watch上的方法和数据github
实例建立完成,并已经完成如下配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调
此时能够调用methods中定义的方法,修改data的数据,而且可触发响应式变化、computed值从新计算,watch到变动等ajax
还未挂载到DOM,不能访问到$el属性,$ref属性内容为空数组vue-router
new Vue({ data () { return { a : 1 } } , created (){ console.log( this.a ) // 1 } })
这个生命周期阶段比较经常使用,好比ajax请求获取初始化数据对实例进行初始化预处理等操做;但要注意在结合vue-router使用时,进入created生命周期阶段后是没法对挂载实例进行拦截的,此时实例已经建立完成;故若是须要某些数据获取完成状况才容许进入页面的场景,建议在路由钩子beforeRouteEnter中实现api
在挂载开始以前被调用数组
注意:从vue生命周期图能够看出
当new Vue({...})的配置中没有el属性时,生命周期暂停,等待vm.$mount(el)调用时才继续浏览器
beforeMount以前,会找到对应的template,并编译成render函数
(这个步骤若是使用.vue文件和运行时版本将会在构建时提早完成)app
template查找的优先级顺序:
template参数 > el 外部HTML
若是指定了render函数,则直接采用render函数,即忽略template参数和el外部HTML
写个栗子测试:
<div id="app">template outside</div> ... import App from './App.vue'; // App是任一Vue组件对象 new Vue({ el: '#app', // template: '<p>template inside</p>', // part inside // render: h => h(App) // part render })
须要Vue完整版本支持,注释part inside和part render依次打开便可观察到三次不一样的结果
Vue的编译过程暂略
el被新建立的$el替换 ---- 怎么理解?
这个能够理解为挂载前为实例寻找了一个暂时容身之处el,编译完成($el建立完成)后替换这个容身之处完成实例的挂载
如:以前那个栗子中,将part render打开后观察生成的DOM结构,<div id="app">template outside</div>
这个节点即原el已经被替换掉
实例挂载到DOM上,此时能够经过DOM API获取到DOM节点,$ref属性能够访问
虽然常常观察到先进入子组件mounted,但根据Vue官方文档:
注意 `mounted` 不会承诺全部的子组件也都一块儿被挂载。若是你但愿等到整个视图都渲染 完毕,能够用 [vm.$nextTick](https://cn.vuejs.org/v2/api/#vm-nextTick)
在这个阶段改变data上的值,相关的computed属性能够马上更新;但须要进入到下一次DOM更新,才能看到DOM上数据更新
栗子:
new Vue({ el: '#app', template: '<p id="testa">{{a}}</p>', router, data () { return { a : 0 } }, mounted() { this.a ++; console.log(this.b); // 2 console.log(document.getElementById('testa').innerHTML) // 0 }, computed :{ b (){ return this.a+1; } } })
beforeRouteEnter的next的勾子比mounted触发还要靠后 - 这个待会说到路由相关钩子时再展开
这里的更新对象是模板,即须要虚拟 DOM 从新渲染和打补丁,beforeUpdate发生在以上两个流程以前,此时新的虚拟DOM已经生成
若是发生变动的数据在模板中并无使用(包括直接和间接,间接:好比某个依赖该数据的计算属性在模板中使用了),则不会触发更新流程!!!
如:
new Vue({ el: '#app', template: '<p id="testa">{{a}}</p>', router, data () { return { a : 0, b : 1 } }, mounted (){ this.b ++; // b并无在模板中使用 }, beforeUpdate (){ debugger; // 不会进入这个断点 } })
在一些参考文章中看到:在这个钩子函数中,能够对状态进行进一步更改,不会再次触发重渲染流程
--- 这个说法有问题
若是对状态进行变动会致使从新进入beforeUpdate(这里变动的状态一样要在模板中使用,若是变动没有在模板中使用的data,才不会再次触发重渲染流程)
并且若变动操做不是基础类型的简单赋值,还会引发死循环(不断从新进入beforeUpdate)!
看看这个栗子,依次把注释打开测试
new Vue({ el: '#app', template: '<p id="testa">{{a}}</p>', router, data () { return { a : 0, c: 0 } }, beforeUpdate() { console.log(document.getElementById('testa').innerHTML) // this.c = 1; // this.c没有在模板中使用,变动不会引发重渲染流程 // this.a = 3; // 会再次进入一次重渲染流程,第二次进入时发现a还是3,值没有变动,不会再次重渲染 // this.a ++; // 会引发死循环,每次进入重渲染流程时,a的值都会变动 }, updated() { console.log(document.getElementById('testa').innerHTML) } })
应该避免在这个钩子函数中操做数据
因为数据更改致使的虚拟 DOM 从新渲染和打补丁,在这以后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,能够执行依赖于 DOM 的操做
注意 `updated` 不会承诺全部的子组件也都一块儿被重绘。若是你但愿等到整个视图都重绘完毕, 能够用 [vm.$nextTick](https://cn.vuejs.org/v2/api/#vm-nextTick)
一样,应该避免在这个钩子函数中操做数据
实例销毁以前调用。在这一步,实例仍然彻底可用,this仍能获取到实例
通常在这一步中进行:销毁定时器、解绑全局事件、销毁插件对象等操做
Vue 实例销毁后调用。调用后,Vue 实例指示的全部东西都会解绑定,全部的事件监听器会被移除,全部的子实例也会被销毁
注意:vue2.0以后主动调用$destroy()不会移除dom节点,做者不推荐直接destroy这种作法,具体参考https://github.com/vuejs/vue/...,若是实在须要这样用能够在这个生命周期钩子中手动移除dom节点
全局前置守卫
当一个导航触发时,全局前置守卫按照建立顺序调用。守卫是异步解析执行,此时导航在全部守卫 resolve 完以前一直处于 等待中
如何使用:
router.beforeEach((to, from, next) => { console.log('全局前置守卫:beforeEach -- next须要调用') next() })
通常在这个守卫方法中进行全局拦截,好比必须知足某种条件(用户登陆等)才能进入路由的状况
参数to和from都是路由对象Route
next是个Function,有如下几种用法(from api文档)
next
的参数是一个 Error
实例,则导航会被终止且该错误会被传递给 router.onError()
注册过的回调全局解析守卫
和beforeEach相似,区别是在导航被确认以前,同时在全部组件内守卫和异步路由组件被解析以后,解析守卫就被调用
即在 beforeEach 和 组件内beforeRouteEnter 以后
参数和beforeEach一致,也须要调用next对导航确认
全局后置钩子
在全部路由跳转结束的时候调用
这些钩子不会接受 next 函数也不会改变导航自己
可直接定义在路由配置上,和beforeEach方法参数、用法相同
在渲染该组件的对应路由被确认
前调用,用法和参数与beforeEach相似,next须要被主动调用
注意:
beforeRouteEnter (to, from, next) { // 这里还没法访问到组件实例,this === undefined next( vm => { // 经过 `vm` 访问组件实例 }) }
vm
访问组件实例进行赋值等操做在当前路由改变,而且该组件被复用时调用,能够经过this访问实例, next须要被主动调用,不能传回调
以前在手机浏览器中好像发现这个守卫的bug?@TODO 待确认
导航离开该组件的对应路由时调用,能够访问组件实例 this
,next须要被主动调用,不能传回调
结合并扩展Vue-router官方文档的说明:
非重用组件,开始组件实例的生命周期