• 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

  • 相关阅读:
    Python3入门基础--str常用方法
    大学jsp实验4include,forword
    大学jsp实验3include指令的使用
    初识MFC----运行时类信息机制
    状态栏
    工具栏
    菜单栏
    程序启动画面
    字符串的截取
    字符串相关类
  • 原文地址:https://www.cnblogs.com/hsp-blog/p/9385904.html
Copyright © 2020-2023  润新知