Vue源码思维导图------------Vue选项的合并之$options

  本节将看下初始化中的$options:

   

 1   Vue.prototype._init = function (options?: Object) {
 2     const vm: Component = this
 3     // a uid
 4     vm._uid = uid++
 5 
 6     // a flag to avoid this being observed
 7     vm._isVue = true
 8     // merge options
 9     if (options && options._isComponent) {
10       // optimize internal component instantiation
11       // since dynamic options merging is pretty slow, and none of the
12       // internal component options needs special treatment.
13       initInternalComponent(vm, options)
14     } else {
15       vm.$options = mergeOptions(
16         // merge Vue.option
17         resolveConstructorOptions(vm.constructor),
18         // new Vue(data) data for object
19         options || {},
20         // current instance
21         vm
22       )
23     }
24 ………………………………
25 }

 通过上边的代码可以看到 ,初始化时vm.$options被mergeOptions方法赋值。那么mergeOptions又做了哪些事情呢?

一. 检查组件名称是否符合要求(  1.是否由字母和-组成,并且以字母开头;2.检测你所注册的组件是否是内置的标签)

 1   if (process.env.NODE_ENV !== 'production') {
 2     checkComponents(child)
 3   }
 4 
 5 /**
 6  * Validate component names
 7  */
 8 function checkComponents (options: Object) {
 9   for (const key in options.components) {
10     validateComponentName(key)
11   }
12 }
13 
14 export function validateComponentName (name: string) {
15   if (!/^[a-zA-Z][\w-]*$/.test(name)) {
16     warn(
17       'Invalid component name: "' + name + '". Component names ' +
18       'can only contain alphanumeric characters and the hyphen, ' +
19       'and must start with a letter.'
20     )
21   }
22   if (isBuiltInTag(name) || config.isReservedTag(name)) {
23     warn(
24       'Do not use built-in or reserved HTML elements as component ' +
25       'id: ' + name
26     )
27   }
28 }

export const isBuiltInTag = makeMap('slot,component', true)

二.  规范化 (props, inject,directives)

1  normalizeProps(child, vm)
2  normalizeInject(child, vm)
3  normalizeDirectives(child)
 1 /**
 2  * Ensure all props option syntax are normalized into the
 3  * Object-based format.
 4  */
 5 function normalizeProps (options: Object, vm: ?Component) {
 6   const props = options.props
 7   if (!props) return
 8   const res = {}
 9   let i, val, name
10   if (Array.isArray(props)) {
11     i = props.length
12     while (i--) {
13       val = props[i]
14       if (typeof val === 'string') {
15         name = camelize(val)
16         res[name] = { type: null }
17       } else if (process.env.NODE_ENV !== 'production') {
18         warn('props must be strings when using array syntax.')
19       }
20     }
21   } else if (isPlainObject(props)) {
22     for (const key in props) {
23       val = props[key]
24       name = camelize(key)
25       res[name] = isPlainObject(val)
26         ? val
27         : { type: val }
28     }
29   } else if (process.env.NODE_ENV !== 'production') {
30     warn(
31       `Invalid value for option "props": expected an Array or an Object, ` +
32       `but got ${toRawType(props)}.`,
33       vm
34     )
35   }
36   options.props = res
37 }
38 
39 /**
40  * Normalize all injections into Object-based format
41  */
42 function normalizeInject (options: Object, vm: ?Component) {
43   const inject = options.inject
44   if (!inject) return
45   const normalized = options.inject = {}
46   if (Array.isArray(inject)) {
47     for (let i = 0; i < inject.length; i++) {
48       normalized[inject[i]] = { from: inject[i] }
49     }
50   } else if (isPlainObject(inject)) {
51     for (const key in inject) {
52       const val = inject[key]
53       normalized[key] = isPlainObject(val)
54         ? extend({ from: key }, val)
55         : { from: val }
56     }
57   } else if (process.env.NODE_ENV !== 'production') {
58     warn(
59       `Invalid value for option "inject": expected an Array or an Object, ` +
60       `but got ${toRawType(inject)}.`,
61       vm
62     )
63   }
64 }
65 
66 /**
67  * Normalize raw function directives into object format.
68  */
69 function normalizeDirectives (options: Object) {
70   const dirs = options.directives
71   if (dirs) {
72     for (const key in dirs) {
73       const def = dirs[key]
74       if (typeof def === 'function') {
75         dirs[key] = { bind: def, update: def }
76       }
77     }
78   }
79 }

三. Vue 选项的合并

 1   const options = {}
 2   let key
 3   for (key in parent) {
 4     mergeField(key)
 5   }
 6   for (key in child) {
 7     if (!hasOwn(parent, key)) {
 8       mergeField(key)
 9     }
10   }
11   function mergeField (key) {
12     const strat = strats[key] || defaultStrat
13     options[key] = strat(parent[key], child[key], vm, key)
14   }

高清原图地址:https://github.com/huashuaipeng/vue--/blob/master/vm.%24options%20%EF%BC%88Vue%E5%AE%9E%E4%BE%8B%E4%B8%8A%E7%9A%84%24options%EF%BC%89.png

代码参考:

https://github.com/vuejs/vue/blob/dev/src/core/util/options.js

官网:

https://cn.vuejs.org/v2/api/#vm-options

猜你喜欢

转载自www.cnblogs.com/hsp-blog/p/9385904.html