In Vue, mixins provide a very flexible way to distribute reusable functionality in Vue components. A Mixin object can contain any component option. When a component uses a Mixin object, the options for all Mixin objects are “blended” into the options for the component itself.

The characteristics of a Mixin

  • Logic can be reused, and variables are independent, independent of each other within components
  • Mixins are prone to name conflicts, so it is important to ensure that there are no conflicting property names when using mixins, which creates an additional naming burden

The use of the Mixin

Global usage

Vue.mixin({ data() { return { myOption: "hello" }; }, created() { console.log(this.myOption, 'this.myOption'); }}); new Vue({ router, store, render: h => h(App) }).$mount('#app'); // Every child component will print hello when it is loaded.Copy the code

Mixins can also be registered globally. Use with extreme care! Once a global mixin is used, it affects every component created later (for example, every child component).

Local Mixin

const myMixin = { data() { return { myOption: 'hello' } } } export defualt { mixins:[myMixin], created(){ console.log(this.myOption,'this.myOption'); }} // So that only mixins in child components will be merged // => "hello"Copy the code

When components and mixin objects have options with the same name, those options are “merged” in the appropriate way.

Mixin’s merge strategy

When using mixins, whether local or global, options with the same name in a component are merged in a way. How did this merge come about? How do you define it? At this point, you have to take a look at how mixins are defined in the Vue source code.

Vue. Mixin source code

// /src/core/global-api/mixin.js import { mergeOptions } from '.. /util/index' export function initMixin (Vue: GlobalAPI) { Vue.mixin = function (mixin: Object) { this.options = mergeOptions(this.options, mixin) return this } }Copy the code

At this time, it can be found that the most important thing is to merge the basic options and mixins with the mergeOtpions method. Now how is the mergeOptions method implemented?

// /src/core/util/options.js export function mergeOptions ( parent: Object, child: Object, vm? : Component ): Object { ... // normalizeProps(child, VM) normalizeInject(child, Vm) normalizeDirectives(child) // Here comments out some of the cases that require recursive determination of the existence of mixins... const options = {} let key for (key in parent) { mergeField(key) } for (key in child) { if (! hasOwn(parent, key)) { mergeField(key) } } function mergeField (key) { const strat = strats[key] || defaultStrat options[key] = strat(parent[key], child[key], vm, key) } return options }Copy the code

The main meanings of the above code are as follows: 1. Recursive processing of mixins; 2. Traversing key in parent and then calling mergeField for merging

// SRC /core/util/options.js import config from '.. / config 'const strats = config. OptionMergeStrategies / / merge data strats, data = function (parentVal: any childVal: any, vm? : Component ): ? Function {// how to merge... Function (parentVal:? Object, childVal: ? Object, vm? : Component, key: string ): ? Object {// Do not consider how to merge... }Copy the code

The basis of the options

  • Data: Data, props, propsData, Computed, Methods, Watch
  • DOM:el,template,render,renderError
  • Lifecycle hooks:
  • Resources: Directives, filters, Components
  • Combination: parent, extends, provide, inject

Can find strats is config optionMrgeStrategies, use this internal data to implement the Vue, watch, props and so on some of the merger strategy, and config. OptionMergeStrategies specific what is? It’s just an empty object, so can we customize the merge strategy with this? The answer is: of course you can

Customize the merge policy

Custom options When merging, the default policy is simply to overwrite existing values. If you want a custom options with custom logic to merge, can be in Vue. Config. OptionMergeStrategies add a function:

Vue.config.optionMergeStrategies.customOption = (toVal, fromVal) => {
  // return mergedVal
}
Copy the code

The merge policy accepts the value of this option defined on the parent and child instances as the first and second arguments, respectively.

Vue.config.optionMergeStrategies.myMixin = function (toVal, fromVal) {
    console.log(toVal, fromVal);
    // => undefined "parent"
    // => parent reportList
    return fromVal || toVal;
};
const myMixin = {
    myMixin: 'parent'
};
export default {
    myMixin: 'reportList',
    mixins: [myMixin],
    created(){
        console.log(this.$options.myMixin);
        // => reportList
    }
}
Copy the code

Although you can customize the merge strategy, it is recommended not to use existing options (such as data, props, Watch, methods, etc.) in Vue to merge. This will conflict with the original logic.

conclusion

In Vue 2, mixins and merge policies are the main tools for abstracting parts of component logic into reusable chunks. However, they have several problems:

  • Mixins are prone to conflicts: because the properties of each feature are merged into the same component, you still need to know about each of the other features to avoid property name collisions and debugging.

  • Reusability is limited: we cannot pass any parameters to mixins to change their logic, which reduces their flexibility in abstract logic.

To solve these problems, Vue3 has a new approach: a composite API

Reference:

Blog.csdn.net/qq_25324335… zhuanlan.zhihu.com/p/105023040