经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTML/CSS » HTML5 » 查看文章
Vue 2.0 深入源码分析(九) 生命周期详解
来源:cnblogs  作者:大沙漠  时间:2019/6/21 12:26:50  对本文有异议

 用法


先来看看官网的介绍:

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

beforeCreate、created、beforeMount、mounted、beforeupdate、updated   、beforeDestroy和destroyed,分别对应八个不同的时期,另外还有两个activated和deactivated生命周期是对应Keep-Alive组件的

关于这八个生命周期的具体用法官网介绍的很详细了,飞机入口:点我点我 ,另外还有一张比较直观图形介绍,飞机入口:点我点我

例如:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  6. <title>Document</title>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <p>{{message}}</p>
  11. <button @click="test1()">测试(更新操作)</button>
  12. <button @click="test2()">测试(销毁操作)</button>
  13. </div>
  14. <script>
  15. Vue.config.productionTip=false;
  16. Vue.config.devtools=false;
  17. new Vue({
  18. el:'#app',
  19. data:{message:"Hello World!"},
  20. beforeCreate:function(){ console.log('beforeCreate'); },
  21. created:function(){ console.log('created'); },
  22. beforeMount:function(){ console.log('beforeMount'); },
  23. mounted:function(){ console.log('mounted'); },
  24. beforeUpdate:function(){ console.log('beforeUpdate'); },
  25. updated:function(){ console.log('updated'); },
  26. beforeDestroy:function(){ console.log('beforeDestroy'); },
  27. destroyed:function(){ console.log('destroyed'); },
  28. methods:{
  29. test1:function(){this.message="Hello Vue!";},
  30. test2:function(){this.$destroy();},
  31. }
  32. })
  33. </script>
  34. </body>
  35. </html>

页面渲染如下:

渲染完成后控制台输出:

当点击了测试(更新操作)这个按钮后,修改了Vue实例的message值做了更新操作,此时控制台输出如下:

当我们点击测试(销毁操作)按钮时,Vue实例做了销毁操作,控制台输出如下:

 对于Vue的插件(包括官方的生态)来说,绝大多数都用到了beforeCreate()这个生命周期函数,可以在实例化前混入一些属性,以vuex为例,如下:

  1. function applyMixin (Vue) {
  2. var version = Number(Vue.version.split('.')[0]);
  3. if (version >= 2) {
  4. Vue.mixin({ beforeCreate: vuexInit }); //如果Vue的版本大于2,则将vuexInit混入到beforeCreate生命周期函数,这样vuex就会进行初始化
  5. } else {
  6. // override init and inject vuex init procedure
  7. // for 1.x backwards compatibility.
  8. var _init = Vue.prototype._init;
  9. Vue.prototype._init = function (options) {
  10. if ( options === void 0 ) options = {};
  11. options.init = options.init
  12. ? [vuexInit].concat(options.init)
  13. : vuexInit;
  14. _init.call(this, options);
  15. };
  16. }

vue-router也是的,如下:

  1. Vue.mixin({ //混入了两个生命周期,分别是beforeCreate和destroyed
  2. beforeCreate: function beforeCreate () {
  3. if (isDef(this.$options.router)) {
  4. this._routerRoot = this;
  5. this._router = this.$options.router;
  6. this._router.init(this);
  7. Vue.util.defineReactive(this, '_route', this._router.history.current);
  8. } else {
  9. this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;
  10. }
  11. registerInstance(this, this);
  12. },
  13. destroyed: function destroyed () {
  14. registerInstance(this);
  15. }
  16. });

 

源码分析


 生命周期的源码实现比较简单,都是通过Vue内部的一个叫callHook()的全局函数执行的,如下:

  1. function callHook (vm, hook) { //第2914行 vm:vue实例 hook:对应的操作名(例如:beforeCreate、created等)
  2. // #7573 disable dep collection when invoking lifecycle hooks
  3. pushTarget();
  4. var handlers = vm.$options[hook]; //获取生命周期函数
  5. if (handlers) {
  6. for (var i = 0, j = handlers.length; i < j; i++) { //遍历生命周期函数
  7. try {
  8. handlers[i].call(vm); //执行该函数,以vm作为上下文
  9. } catch (e) {
  10. handleError(e, vm, (hook + " hook"));
  11. }
  12. }
  13. }
  14. if (vm._hasHookEvent) {
  15. vm.$emit('hook:' + hook);
  16. }
  17. popTarget();
  18. }

beforeCreate和created是在init()的时候执行的,如下:

  1. Vue.prototype._init = function (options) { //第4576行
  2. /**/
  3. vm._self = vm;
  4. initLifecycle(vm);
  5. initEvents(vm);
  6. initRender(vm);
  7. callHook(vm, 'beforeCreate'); //执行beforeCreate生命周期函数
  8. initInjections(vm); // resolve injections before data/props
  9. initState(vm);
  10. initProvide(vm); // resolve provide after data/props
  11. callHook(vm, 'created'); //执行created生命周期函数
  12.  
  13. /**/
  14. };

beforeMount和mounted是在挂载的时候在mountComponent()里执行的,如下:

  1. function mountComponent(vm, el, hydrating) { //第2739行 挂载组件 vm:Vue实例 el:真实的DOM节点对象
  2. /**/
  3. callHook(vm, 'beforeMount'); //挂载前 执行生命周期里的beforeMount事件
  4. var updateComponent;
  5. if ("development" !== 'production' && config.performance && mark) { //开启了性能追踪时的分支
  6. /**/
  7. } else {
  8. updateComponent = function () {vm._update(vm._render(), hydrating);};
  9. }
  10. new Watcher(vm, updateComponent, noop, null, true);
  11. hydrating = false;
  12. if (vm.$vnode == null) {
  13. vm._isMounted = true; //设置vm._isMounted为true,表示已挂载
  14. callHook(vm, 'mounted'); //执行生命周期里的Mount事件
  15. }
  16. return vm
  17. }

beforeUpdate是在Vue原型上的_update更新时触发的,如下:

  1. Vue.prototype._update = function (vnode, hydrating) { //第2646行
  2. var vm = this;
  3. if (vm._isMounted) { //如果已经挂载了,则表示已经挂载了
  4. callHook(vm, 'beforeUpdate'); //则触发beforeUpdate
  5. }
  6. /**/
  7. }

updated是在nextTick()执行时当watcher执行完了之后触发的,如下:

  1. function callUpdatedHooks (queue) { //第3016行
  2. var i = queue.length;
  3. while (i--) {
  4. var watcher = queue[i];
  5. var vm = watcher.vm;
  6. if (vm._watcher === watcher && vm._isMounted) { //如果当前是渲染watcher,且已经挂载了
  7. callHook(vm, 'updated'); //则触发update生命周期函数
  8. }
  9. }
  10. }

beforeDestroy和destroyed是在Vue原型的$destroy()方法里触发的,如下:

  1. Vue.prototype.$destroy = function () { //第2695行
  2. var vm = this;
  3. if (vm._isBeingDestroyed) {
  4. return
  5. }
  6. callHook(vm, 'beforeDestroy'); //触发beforeDestroy生命周期函数
  7. /*这里进行销毁过程*/
  8. callHook(vm, 'destroyed'); //触发destroyed生命周期函数
  9. /**/
  10. };
  11. }

 

原文链接:http://www.cnblogs.com/greatdesert/p/11062881.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号