用法 先來看看官網的介紹: 主要有八個生命周期,分別是: beforeCreate、created、beforeMount、mounted、beforeupdate、updated 、beforeDestroy和destroyed,分別對應八個不同的時期,另外還有兩個activated和deacti ...
用法
先來看看官網的介紹:
主要有八個生命周期,分別是:
beforeCreate、created、beforeMount、mounted、beforeupdate、updated 、beforeDestroy和destroyed,分別對應八個不同的時期,另外還有兩個activated和deactivated生命周期是對應Keep-Alive組件的
關於這八個生命周期的具體用法官網介紹的很詳細了,飛機入口:點我點我 ,另外還有一張比較直觀圖形介紹,飛機入口:點我點我
例如:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <title>Document</title> </head> <body> <div id="app"> <p>{{message}}</p> <button @click="test1()">測試(更新操作)</button> <button @click="test2()">測試(銷毀操作)</button> </div> <script> Vue.config.productionTip=false; Vue.config.devtools=false; new Vue({ el:'#app', data:{message:"Hello World!"}, beforeCreate:function(){ console.log('beforeCreate'); }, created:function(){ console.log('created'); }, beforeMount:function(){ console.log('beforeMount'); }, mounted:function(){ console.log('mounted'); }, beforeUpdate:function(){ console.log('beforeUpdate'); }, updated:function(){ console.log('updated'); }, beforeDestroy:function(){ console.log('beforeDestroy'); }, destroyed:function(){ console.log('destroyed'); }, methods:{ test1:function(){this.message="Hello Vue!";}, test2:function(){this.$destroy();}, } }) </script> </body> </html>
頁面渲染如下:
渲染完成後控制台輸出:
當點擊了測試(更新操作)這個按鈕後,修改了Vue實例的message值做了更新操作,此時控制台輸出如下:
當我們點擊測試(銷毀操作)按鈕時,Vue實例做了銷毀操作,控制台輸出如下:
對於Vue的插件(包括官方的生態)來說,絕大多數都用到了beforeCreate()這個生命周期函數,可以在實例化前混入一些屬性,以vuex為例,如下:
function applyMixin (Vue) {
var version = Number(Vue.version.split('.')[0]);
if (version >= 2) {
Vue.mixin({ beforeCreate: vuexInit }); //如果Vue的版本大於2,則將vuexInit混入到beforeCreate生命周期函數,這樣vuex就會進行初始化
} else {
// override init and inject vuex init procedure
// for 1.x backwards compatibility.
var _init = Vue.prototype._init;
Vue.prototype._init = function (options) {
if ( options === void 0 ) options = {};
options.init = options.init
? [vuexInit].concat(options.init)
: vuexInit;
_init.call(this, options);
};
}
vue-router也是的,如下:
Vue.mixin({ //混入了兩個生命周期,分別是beforeCreate和destroyed
beforeCreate: function beforeCreate () {
if (isDef(this.$options.router)) {
this._routerRoot = this;
this._router = this.$options.router;
this._router.init(this);
Vue.util.defineReactive(this, '_route', this._router.history.current);
} else {
this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
}
registerInstance(this, this);
},
destroyed: function destroyed () {
registerInstance(this);
}
});
源碼分析
生命周期的源碼實現比較簡單,都是通過Vue內部的一個叫callHook()的全局函數執行的,如下:
function callHook (vm, hook) { //第2914行 vm:vue實例 hook:對應的操作名(例如:beforeCreate、created等) // #7573 disable dep collection when invoking lifecycle hooks pushTarget(); var handlers = vm.$options[hook]; //獲取生命周期函數 if (handlers) { for (var i = 0, j = handlers.length; i < j; i++) { //遍歷生命周期函數 try { handlers[i].call(vm); //執行該函數,以vm作為上下文 } catch (e) { handleError(e, vm, (hook + " hook")); } } } if (vm._hasHookEvent) { vm.$emit('hook:' + hook); } popTarget(); }
beforeCreate和created是在init()的時候執行的,如下:
Vue.prototype._init = function (options) { //第4576行 /*略*/ vm._self = vm; initLifecycle(vm); initEvents(vm); initRender(vm); callHook(vm, 'beforeCreate'); //執行beforeCreate生命周期函數 initInjections(vm); // resolve injections before data/props initState(vm); initProvide(vm); // resolve provide after data/props callHook(vm, 'created'); //執行created生命周期函數 /*略*/ };
beforeMount和mounted是在掛載的時候在mountComponent()里執行的,如下:
function mountComponent(vm, el, hydrating) { //第2739行 掛載組件 vm:Vue實例 el:真實的DOM節點對象 /*略*/ callHook(vm, 'beforeMount'); //掛載前 執行生命周期里的beforeMount事件 var updateComponent; if ("development" !== 'production' && config.performance && mark) { //開啟了性能追蹤時的分支 /*略*/ } else { updateComponent = function () {vm._update(vm._render(), hydrating);}; } new Watcher(vm, updateComponent, noop, null, true); hydrating = false; if (vm.$vnode == null) { vm._isMounted = true; //設置vm._isMounted為true,表示已掛載 callHook(vm, 'mounted'); //執行生命周期里的Mount事件 } return vm }
beforeUpdate是在Vue原型上的_update更新時觸發的,如下:
Vue.prototype._update = function (vnode, hydrating) { //第2646行 var vm = this; if (vm._isMounted) { //如果已經掛載了,則表示已經掛載了 callHook(vm, 'beforeUpdate'); //則觸發beforeUpdate } /*略*/ }
updated是在nextTick()執行時當watcher執行完了之後觸發的,如下:
function callUpdatedHooks (queue) { //第3016行 var i = queue.length; while (i--) { var watcher = queue[i]; var vm = watcher.vm; if (vm._watcher === watcher && vm._isMounted) { //如果當前是渲染watcher,且已經掛載了 callHook(vm, 'updated'); //則觸發update生命周期函數 } } }
beforeDestroy和destroyed是在Vue原型的$destroy()方法里觸發的,如下:
Vue.prototype.$destroy = function () { //第2695行 var vm = this; if (vm._isBeingDestroyed) { return } callHook(vm, 'beforeDestroy'); //觸發beforeDestroy生命周期函數 /*這裡進行銷毀過程*/ callHook(vm, 'destroyed'); //觸發destroyed生命周期函數 /*略*/ }; }