The source code comments are as follows

Merge two option objects into a new one. Core utility used in both instantiation and inheritance.

The function of mergeOptions is to merge two Options objects and generate a new object. Is the core method used in instantiation and inheritance. You can see the importance of the mergeOptions method.

src/core/util/options.js

export function mergeOptions (
    parent: Object,     //Options Child: Object on the constructor of this instance,//Options VM passed in during instantiation? : Component//The instance itself) :Object {
    // Check whether the name of the options.components option passed in matches the rules (not built-in tags)
    if(process.env.NODE_ENV ! = ='production') {
        checkComponents(child)
    }

    if (typeof child === 'function') {
        child = child.options
    }

    // Convert the passed child-props to a hump object representation.
    // props can use array and object syntax,
    // But internally it is retraversed and encapsulated in a new object.
    normalizeProps(child, vm)

    normalizeInject(child, vm)

    // Directives use the syntax of the cache object. The values of the properties in the object can only be functions, which bind the functions to the bind and update functions of the directives
    normalizeDirectives(child)

    // If extends exists, it is incorporated into the parent object and then into its own child. Extends is preferably an object syntax
    const extendsFrom = child.extends
    if (extendsFrom) {
        parent = mergeOptions(parent, extendsFrom, vm)
    }

    // If there are mixins, the contents of the mixins are merged into the parent object and then merged with the child object. Mixins can only be array syntax
    if (child.mixins) {
        for (let i = 0, l = child.mixins.length; i < l; i++) {
            parent = mergeOptions(parent, child.mixins[i], vm)
        }
    }

    // Initialize an object to store the merged contents of the parent and child and return it as the result of the mergeOptions function
    const options = {}
    let key
    for (key in parent) {
        mergeField(key)
    }
    for (key in child) {
        if(! hasOwn(parent, key)) { mergeField(key) } }// Merge parent and child with the policy object
    function mergeField (key) {
        const strat = strats[key] || defaultStrat
        options[key] = strat(parent[key], child[key], vm, key)
    }

    return options
}
Copy the code

The parent, child, and vm parameters are options passed to the constructor, options passed to the instantiation, and the instance itself. Finally, the merged options are returned. Check that the name of the options.components option passed in matches the rule, and then call

normalizeProps(child, vm)
normalizeInject(child, vm)
normalizeDirectives(child)  
Copy the code

Format the props, Inject, and directives in options and convert them to objects

normalizeeProps

When props is an array, as in the following case


Vue.component('blog-post', {
    props: ['postTitle'].template: '<h3>{{ postTitle }}</h3>'
})
Copy the code

The processing logic is to traverse the props array, taking the value of each item as the key of the RES object, value equal to {type: null}, which converts [‘postTitle’] from the example above to the following form

{
    postTitle: { type: null}}Copy the code

When props are objects, as in the following case

Vue.component('my-component', {
  props: {
    // A mandatory string
    propC: {
        type: String.required: true}}})Copy the code

The logic in this case is to traverse the object, first converting the object’s key to a hump. And then determine the value of the object, if it is pure object (namely the call object. The prototype. The result of the toString method is [object object]), then the object directly to the value assigned to the res, if not, then the type: the value of the object is assigned to attach res. And eventually this form will be converted to

{
    propC: {
        type: String.required: true}}Copy the code

normalizeInject

Similar to normalizeProps

// array
var Child = {
    inject: ['foo'],
    created () {
        console.log(this.foo) // => "bar"
    }
  // ...
}

// object
const Child = {
    inject: {
        foo: {
            from: 'bar'.default: 'foo'}}}/ / = = = = = = = = = = = = = = = = = = = = = =
/ / after the transformation

// array
{
    foo: { from: 'foo'}}// object
{
    foo: {
        from: 'bar'.default: 'foo'}}Copy the code

normalizeDirectives

Method is mainly to deal with some custom instructions, the method processing logic here is mainly for the case of the function shorthand in the custom instructions.

Vue.directive('color'.function (el, binding) {
    el.style.backgroundColor = binding.value
})

/ / = = = = = = = = = = = = = = = = = = = = = =
/ / after the transformation

color: {
    bind: function (el, binding) {
        el.style.backgroundColor = binding.value
    },
    update: function (el, binding) {
        el.style.backgroundColor = binding.value
    }
}
Copy the code

Let’s move on to the code

.// If extends exists, it is incorporated into the parent object and then into its own child. Extends is preferably an object syntax
const extendsFrom = child.extends
if (extendsFrom) {
    parent = mergeOptions(parent, extendsFrom, vm)
}

// If there are mixins, the contents of the mixins are merged into the parent object and then merged with the child object. Mixins can only be array syntax
if (child.mixins) {
    for (let i = 0, l = child.mixins.length; i < l; i++) {
        parent = mergeOptions(parent, child.mixins[i], vm)
    }
}
...
Copy the code

The logic behind this code is that when an options is passed with a mixin or extends property, Again call mergeOptions method combined mixins and extends the content to instance constructor options (i.e., the parent options) such as below this kind of situation, will the incoming mounted, created a hook handler, Methods are proposed to merge with parent options.

const myMixin = {
    created: function () {
        this.hello()
    },
    methods: {
        hello: function () {
            console.log('hello from mixin')}}}const myComponent = {
    mounted: function () {
        this.goodbye()
    },
    methods: {
        goodbye: function () {
            console.log('goodbye from mixin')}}}const childComponent = Vue.component('child', {... mixins: [myMixin],extends: myComponent
    ...
})
Copy the code

Next comes the core of mergeOption’s merge strategy

 // Merge parent and child with the policy object
function mergeField (key) {
    const strat = strats[key] || defaultStrat
    options[key] = strat(parent[key], child[key], vm, key)
}
Copy the code
// The default merge policy
// If the attribute on child exists, take the attribute on child, otherwise take the attribute on parent
const defaultStrat = function (parentVal: any, childVal: any) :any {
    return childVal === undefined
        ? parentVal
        : childVal
}
Copy the code

Merger strategy to strat values for the strats [key] | | defaultStrat, defaultStrat namely, if the property exists on the child, take the child’s properties, or take on the parent attribute, Strats will options. OptionMergeStrategies and vue default merger strategy integration, we can see that is already defined in the vue merger strategies below