Vue.extend
-
1.我们经常会在封装一些全局的组件(类似公共弹窗这种)代码里面, 看到 Vue.extend 方法, 但是初学的时候, 会对这个东西很模糊, 就知道是 Vue 的子类, 在封装的时候
创建出对应的实例, 然后就能调用$mount 方法, 挂载一个元素就完了, 但对其内部实现原理并不清楚 -
2.Vue.extend 作用创建出一个 Vue 的子类, 在 Vue 源码内部, Vue.extend 经常作为组件的构造函数出现, 而想要搞懂组件的渲染原理以及数据变化之后的更新操作, 就必须
理解 Vue.extend 方法 -
3.源码分析
-
(1).Vue.extend 内部会创建一个 Sub 构造函数, Sub 构造函数内部会调用 this._init 方法, new Sub 传进来的参数会传到_init 方法中(这块涉及到了组件的初次渲染流程, 下一篇就会讲到这个参数传进来的作用了)
-
(2).Vue.extend 方法调用后返回 Vue 的子类, 是怎么做到的呢? 其实很简单, Sub 构造函数创建完之后, Sub.prototype = Object.create(Vue), 这其实就已经创建出来一个子类了, 比如说我们现在想调用mount方法了, 那js引擎就会先去Sub实例上面找, 找不到就去实例.__proto__也就是Object.create创建出来的这个对象找, 找不到就去对象的原型也就是Vue上面, 在这个上面就有我们需要的$mount 方法
-
那为什么不直接Sub.prototype = Vue呢? 构造函数身上的prototype原型上面有一个constructor又指回了这个构造函数, 那如果直接赋值的话, 是不是应该将Vue.constructor变成Sub, 但是这样做合适吗, 我们向Vue构造函数身上增加了 -
一个静态方法, 但这个方法和Vue内部自身有关系吗? 如果我们不知道有Vue.extend, 直接将Vue.constructor打印出来, 那看的肯定是一脸懵逼的, 所以这块是通过创建一个对象来实现继承的, 并没有影响到Vue本身 -
(3).Sub.prototype.constructor = Sub, 1 创建 Sub 构造函数 2 改变构造函数原型 3 增加构造函数原型身上的 constructor 属性
-
(4). 接下来这块就是 Sub 函数中最重要的一步了, Sub.options = mergOptions(Vue.options, options)
Vue.options 指的是定义的一些全局组件, 指令这种, 比如 Vue.components(‘aaa’, {}), Vue.components(‘aaa’, {})就等同于 Vue.options.components.aaa = {}, 源码内部就是这样实现的, 所以 Vue 会将全局的一些东西全部放到 Vue.options 里面
new Vue({ components: { aaa: 配置对象 } }), 这个配置对象会通过Vue.extned()作为参数传进来,会变成我们自己写的options 在这里只需要先记住即可
mergOptions 方法会将定义在 Vue 全局上面的 options 与我们自己写的 options 进行合并, 为什么进行合并, 我们想一下, 如果有一个同名的局部组件和全局组件, 那我们应该用全局还是局部的, 这个时候对两个组件对象是不是需要进行合并, 确定到底使用全局的还是局部的
mergeOptions 方法返回一个对象, (我用父代表 Vue.options, 用子表示组件的 options 对象) -
a: mergeOptions方法会遍历父选项, 遍历每一项时, 去子选项里面看一看有没有, 如果没有就表示只有父有, 那就向返回的对象身上增加对应的属性 -
b: mergeOptions还会遍历子选项, 遍历每一项时都去调用mergeField方法, 将每一项传进去 -
c: mergeField方法内部会拿到子选项的每一项, 同时去父选项里面取到对应的那一项, 接着就会判断在Vue内部是否定义了对当前属性(data methods components这种)的合并策略, 如果没有就优先使用子的属性值作为返回的对象里面的那个属性所对应的属性值, 如果有就执行Vue内部的合并策略(这里拿components举例, 因为这个会涉及到后面Vue的渲染过程, 其他的有兴趣的话去源码里面看下) -
components的合并是通过mergeComponents(源码里面可能不叫这个名字, 但是原理都一样)方法实现的, 本质上就是利用原型链, 创建出一个空对象, 用父选项的components作为空对象的原型, 接着遍历子选项的components, 为这个空对象里面添加属性, 这样就实现了先在子选项的components查找, 找不到的话才根据原型去父选项的components上查找, 也就是先查找局部组件, 局部组件找不到才会去查找全局组件执行完之后Sub.options就已经将自身与全局的全部合并起来了
-
(5). 最后再将Sub构造函数返回, 这个就是Vue.extend的基本原理, 大概也就三步, 1创建构造函数 2改变构造函数原型指向Vue 3合并全局属性
1358

被折叠的 条评论
为什么被折叠?



