1. 程式人生 > >Vue源碼思維導圖------------Vue選項的合並之$options

Vue源碼思維導圖------------Vue選項的合並之$options

character treat let 官網 tst spa sre 分享圖片 技術分享

本節將看下初始化中的$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

Vue源碼思維導圖------------Vue選項的合並之$options