(Vue)简述 mixin、extends 的介绍以及覆盖逻辑
mixin 和 extends 均是用于合并、拓展组件的,两者均通过mergeOptions 方法实现合并。
mergeOptions 的执行过程
规范化选项:
normalizeProps
:用于处理组件的props
选项。确保props
被转化成统一的格式,以便后续处理。normalizeInject
:处理组件的inject
选项,确保inject
被转化成标准的对象格式。normalizeDirectives
:处理组件的directives
选项,确保其格式正确。对未合并的选项进行判断:
- 未合并的选项包括默认选项、全局选项、和局部选项。
- 通过一定的策略,判断如何合并这些选项。
举例:
考虑以下例子,展示了一个简单的 Vue 组件以及全局混入的情况:
// 全局混入 Vue.mixin({ data() { return { globalData: 'Global Data' }; }, directives: { globalDirective: { // 全局指令定义 } } }); // 组件定义 const Component = Vue.extend({ props: { prop1: String }, data() { return { localData: 'Local Data' }; }, directives: { localDirective: { // 组件指令定义 } } }); // 创建组件实例 const instance = new Component({ propsData: { prop1: 'Value for prop1' }, data() { return { instanceData: 'Instance Data' }; }, directives: { instanceDirective: { // 实例指令定义 } } });
在这个例子中,
mergeOptions
的执行过程可能如下:
规范化选项:
normalizeProps
处理了props
选项。normalizeInject
处理了inject
选项。normalizeDirectives
处理了directives
选项。对未合并的选项进行判断:
- 合并
data
选项:组件实例的data
会覆盖全局混入的data
,而组件定义的data
会覆盖组件实例的data
。- 合并
directives
选项:全局混入的指令、组件定义的指令和组件实例的指令都会被合并到最终的选项中。最终,
instance
中的选项将包含全局混入的data
、组件定义的data
、组件实例的data
,以及合并的指令选项。这个例子展示了对选项的规范化和合并过程,确保了组件在不同层次上的选项都能够被正确处理。请注意,Vue.js 的实际实现可能更加复杂,涉及到更多的选项和逻辑。
Mixin(混入)
想象一下,你有一本美食书,里面有很多不同的烹饪技巧和配方。每一页都是一个mixin
,包含了某个特定的烹饪技巧,比如烤肉的技巧、蒸鱼的方法等。你可以选择一页一页地将这些技巧混入到你的特色菜品中。
在Vue中,当你使用mixin
时,你实际上是将一个对象的属性和方法合并到组件中。如果你在组件和mixin
中都定义了相同的生命周期钩子或方法,Vue会以一种特定的规则来合并它们。这就好比你在美食书和你的食谱中都写了相同的步骤,Vue会自动帮你处理这些步骤的合并。
mixins 接收一个混入对象的数组,其中混入对象可以像正常的实例对象一样包含实例选项,这些选项会被合并到最终的选项中。Mixin钩子按照传入顺序依次调用,并在调用组件自身的钩子之前被调用。
Mixin钩子会按照传入数组的顺序依次调用,而且它们会在调用组件自身的钩子之前执行。这意味着如果在组件和混入对象中都定义了相同名称的生命周期钩子或方法,那么混入对象中的会在组件自身的之前调用。
const myMixin = {
created() {
console.log('Mixin created');
},
};
const myComponent = {
mixins: [myMixin],
created() {
console.log('Component created');
},
};
new Vue(myComponent);
在这个例子中,如果你创建了一个Vue实例,你将会看到以下输出:
Mixin created
Component created
Extends(继承)
现在,假设你有一个徒弟,他想学习你的特色菜的制作方法,但希望在某些步骤上加入他自己的创意。你可以把你的食谱作为一个基础版本,然后他可以在上面进行修改和扩展。
在Vue中,extends
的作用有点像这位徒弟。你可以创建一个基础组件,然后通过extends
创建一个新的组件,新组件将继承基础组件的所有属性和方法。这就好比徒弟继承了你的食谱,然后在上面进行自己的创新。
extends
主要用于创建可扩展的组件构造器,而不仅仅是为了扩展单文件组件。它可以接收一个组件选项对象或构造函数。
-
接收组件选项对象:
const BaseComponent = { // ...组件选项 }; const ExtendedComponent = Vue.extend(BaseComponent);
在这里,
BaseComponent
是一个组件选项对象,通过Vue.extend
创建了一个新的构造函数ExtendedComponent
,该构造函数继承了BaseComponent
的选项。 -
接收构造函数:
const BaseComponent = Vue.extend({ // ...组件选项 }); const ExtendedComponent = Vue.extend(BaseComponent);
在这个例子中,
BaseComponent
直接就是一个由Vue.extend
创建的构造函数,而不是一个组件选项对象。
Vue.extend
返回的是一个新的 Vue 构造函数,而不仅仅是一个组件选项对象。
组件选项对象与构造函数
组件选项对象: 在Vue中,组件选项对象是一个包含组件配置的JavaScript对象。这个对象包括了组件的各种选项,比如
data
、methods
、computed
、created
等等。一个简单的组件选项对象可能如下所示:const myComponentOptions = { data() { return { message: 'Hello, Vue!', }; }, methods: { greet() { console.log(this.message); }, }, };
Vue.extend 创建构造函数:
Vue.extend
是Vue提供的一个方法,用于创建一个可以产生组件实例的构造函数。当你传递一个组件选项对象给Vue.extend
时,它会返回一个新的构造函数。这个构造函数可以用来创建具有相同配置的多个组件实例。const ExtendedComponent = Vue.extend(myComponentOptions);
在这里,
ExtendedComponent
是一个构造函数,它继承了myComponentOptions
中的组件选项。这意味着你可以使用ExtendedComponent
来创建新的组件实例,这些实例将具有相同的数据、方法等。const instance1 = new ExtendedComponent(); const instance2 = new ExtendedComponent();
instance1
和instance2
都是基于ExtendedComponent
构造函数创建的实例,它们共享相同的组件选项。这就是通过Vue.extend
创建的构造函数的作用,它使你能够有效地创建具有相似功能的组件。
通过使用 extends
,你可以轻松地创建基础组件并在其基础上构建更复杂的组件。这在单文件组件中也是有效的,但并不局限于单文件组件。在使用 extends
时,可以通过添加或覆盖属性来定制新组件,使其具有基础组件的功能,并且能够扩展或修改这些功能。
覆盖逻辑
属性 | 合并函数 | 合并策略 |
---|---|---|
data | mergeDataOrFn,mergeData | mixins/extends 只会将自己有的但是组件上没有的内容混合到组件上,重复定义的话默认是使用组件上的,如果data里面有对象,将递归内部对象继续按照该策略合并 |
provide | mergeDataOrFn,mergeData | 同上 |
props | extend | mixins/extends 只会将自己有的但是组件上没有的内容混合到组件上 |
methods | extend | 同上 |
inject | extend | 同上 |
computed | extend | 同上 |
组件,过滤器,指令属性 | extend | 同上 |
el | defaultStrat | 同上 |
propsData | defaultStrat | 同上 |
watch | strats.watch | 合并watch监控的回调方法,执行顺序是先mixins/extends里的watch定义的回调,然后再是组件本身的回调 |
HOOKS生命周期钩子 | mergeHook | 同一种钩子的回调函数会被合并成数组,执行顺序是先mixins/extends里定义的钩子函数然后才是组件里定义的 |
总结
在比喻中,mixin
就像美食书中的各种技巧,而extends
就像徒弟学习和发展自己独特菜品的过程。在使用这两种方式时,了解它们的覆盖逻辑可以帮助你更好地组织和复用你的Vue组件逻辑。
转载自:https://juejin.cn/post/7304538094783741993