加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Vue 2.0 深入源码分析(九) 生命周期详解

发布时间:2020-12-13 23:47:16 所属栏目:Linux 来源:网络整理
导读:? 用法 先来看看官网的介绍: 主要有八个生命周期,分别是: beforeCreate、created、beforeMount、mounted、beforeupdate、updated?? 、beforeDestroy和destroyed,分别对应八个不同的时期,另外还有两个activated和deactivated生命周期是对应Keep-Alive组件

?用法


先来看看官网的介绍:

主要有八个生命周期,分别是:

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生命周期函数
    /**/
  };
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读