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