最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 手写Vue2.0源码-Mixin混入原理

    正文概述 掘金(Big shark@LX)   2021-04-16   452

    前言

    此篇主要手写 Vue2.0 源码-Mixin 混入原理

    上一篇咱们主要介绍了 Vue 异步更新原理 核心是运用 nextTick 实现异步队列 此篇主要包含 Mixin 混入 这是 Vue 里面非常关键的一个 api 在 Vue 初始化的时候起到了合并选项的重要作用

    适用人群: 没时间去看官方源码或者看源码看的比较懵而不想去看的同学


    正文

    Vue.mixin({
      created() {
        console.log("我是全局混入");
      },
    });
    
    // Vue实例化
    let vm = new Vue({
      el: "#app",
      data() {
        return {
          a: { a: { a: { b: 456 } } },
          aa: 1,
          bb: 2,
        };
      },
      created() {
        console.log("我是自己的");
      },
      template: `<div id="a">hello 这是我自己写的Vue{{name}}
              </div>`,
    });
    

    当我们在 Vue 里面想要复用一段业务代码逻辑时经常用到的就是混入的方法 但是对于混入的原理 混入的先后顺序以及不同选项的合并策略大家是否都清楚呢 让我们一起来手写一遍就都清楚了

    1.定义全局 Mixin 函数

    // src/global-api/mixin.js
    
    import {mergeOptions} from '../util/index'
    export default function initMixin(Vue){
      Vue.mixin = function (mixin) {
        //   合并对象
          this.options=mergeOptions(this.options,mixin)
      };
    }
    };
    

    新建 global-api 文件夹 把 mixin 定义为 Vue 的全局方法 核心方法就是利用 mergeOptions 把传入的选项混入到自己的 options 上面

    // src/index.js
    import { initMixin } from "./init.js";
    // Vue就是一个构造函数 通过new关键字进行实例化
    function Vue(options) {
      // 这里开始进行Vue初始化工作
      this._init(options);
    }
    // 此做法有利于代码分割
    initMixin(Vue);
    export default Vue;
    

    然后在 Vue 的入口文件里面引入 initMixin 方法

    2.mergeOptions 方法

    // src/util/index.js
    // 定义生命周期
    export const LIFECYCLE_HOOKS = [
      "beforeCreate",
      "created",
      "beforeMount",
      "mounted",
      "beforeUpdate",
      "updated",
      "beforeDestroy",
      "destroyed",
    ];
    
    // 合并策略
    const strats = {};
    
    //生命周期合并策略
    function mergeHook(parentVal, childVal) {
      // 如果有儿子
      if (childVal) {
        if (parentVal) {
          // 合并成一个数组
          return parentVal.concat(childVal);
        } else {
          // 包装成一个数组
          return [childVal];
        }
      } else {
        return parentVal;
      }
    }
    
    // 为生命周期添加合并策略
    LIFECYCLE_HOOKS.forEach((hook) => {
      strats[hook] = mergeHook;
    });
    
    // mixin核心方法
    export function mergeOptions(parent, child) {
      const options = {};
      // 遍历父亲
      for (let k in parent) {
        mergeFiled(k);
      }
      // 父亲没有 儿子有
      for (let k in child) {
        if (!parent.hasOwnProperty(k)) {
          mergeFiled(k);
        }
      }
    
      //真正合并字段方法
      function mergeFiled(k) {
        if (strats[k]) {
          options[k] = strats[k](parent[k], child[k]);
        } else {
          // 默认策略
          options[k] = child[k] ? child[k] : parent[k];
        }
      }
      return options;
    }
    

    我们先着重看下 mergeOptions 方法 主要是遍历父亲和儿子的属性 进行合并 如果合并的选项有自己的合并策略 那么就是用相应的合并策略

    再来看看 我们这里的生命周期的合并策略 mergeHook 很明显是把全部的生命周期都各自混入成了数组的形式依次调用

    3.生命周期的调用

    // src/lifecycle.js
    
    export function callHook(vm, hook) {
      // 依次执行生命周期对应的方法
      const handlers = vm.$options[hook];
      if (handlers) {
        for (let i = 0; i < handlers.length; i++) {
          handlers[i].call(vm); //生命周期里面的this指向当前实例
        }
      }
    }
    

    把$options 上面的生命周期依次遍历进行调用

    // src/init.js
    
    Vue.prototype._init = function (options) {
      const vm = this;
      // 这里的this代表调用_init方法的对象(实例对象)
      //  this.$options就是用户new Vue的时候传入的属性和全局的Vue.options合并之后的结果
    
      vm.$options = mergeOptions(vm.constructor.options, options);
      callHook(vm, "beforeCreate"); //初始化数据之前
      // 初始化状态
      initState(vm);
      callHook(vm, "created"); //初始化数据之后
      // 如果有el属性 进行模板渲染
      if (vm.$options.el) {
        vm.$mount(vm.$options.el);
      }
    };
    

    在 init 初始化的时候调用 mergeOptions 来进行选项合并 之后在需要调用生命周期的地方运用 callHook 来执行用户传入的相关方法

    // src/lifecycle.js
    export function mountComponent(vm, el) {
      vm.$el = el;
      // 引入watcher的概念 这里注册一个渲染watcher 执行vm._update(vm._render())方法渲染视图
      callHook(vm, "beforeMount"); //初始渲染之前
      let updateComponent = () => {
        vm._update(vm._render());
      };
      new Watcher(
        vm,
        updateComponent,
        () => {
          callHook(vm, "beforeUpdate"); //更新之前
        },
        true
      );
      callHook(vm, "mounted"); //渲染完成之后
    }
    

    在 mountComponent 方法里面调用相关的生命周期 callHook

    4.混入的思维导图

    手写Vue2.0源码-Mixin混入原理

    小结

    至此 Vue 的混入原型已经手写完毕 其实最核心的就是对象合并以及不同选项的合并策略 目前只是演示了生命周期的合并策略 后续到组件的时候会讲到组件相关的合并策略 大家可以看着思维导图自己动手写一遍核心代码哈 遇到不懂或者有争议的地方欢迎评论留言


    起源地下载网 » 手写Vue2.0源码-Mixin混入原理

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元