企业所得税政策最新2023税率台州百度快照优化公司
根据源码分析Vue 组件中 props的实现原理
- 整体功能概述
- 代码详细解释
- 1. 导入模块和类型定义
- 2. `validateProp` 函数
- 3. `getPropDefaultValue` 函数
- 4. `assertProp` 函数
- 5. `assertType` 函数
- 6. 其他辅助函数
- 实现原理总结
整体功能概述
源码实现了一系列用于验证和处理组件 props
的工具函数,主要包括:
validateProp
:验证单个prop
的值,并处理默认值和类型转换。getPropDefaultValue
:获取prop
的默认值。assertProp
:断言prop
是否有效。assertType
:检查值的类型是否符合预期。- 其他辅助函数,如
getType
、isSameType
等。
代码详细解释
1. 导入模块和类型定义
/* @flow */import { warn } from './debug'
import { observe, toggleObserving, shouldObserve } from '../observer/index'
import {hasOwn,isObject,toRawType,hyphenate,capitalize,isPlainObject
} from 'shared/util'type PropOptions = {type: Function | Array<Function> | null,default: any,required: ?boolean,validator: ?Function
};
/* @flow */
:表示该文件使用 Flow 进行静态类型检查。- 导入了多个工具函数和模块,用于调试警告、响应式观察和一些通用工具方法。
PropOptions
定义了prop
的选项类型,包括type
(类型)、default
(默认值)、required
(是否必需)和validator
(自定义验证函数)。
2. validateProp
函数
export function validateProp (key: string,propOptions: Object,propsData: Object,vm?: Component
): any {const prop = propOptions[key]const absent = !hasOwn(propsData, key)let value = propsData[key]// boolean castingconst booleanIndex = getTypeIndex(Boolean, prop.type)if (booleanIndex > -1) {if (absent && !hasOwn(prop, 'default')) {value = false} else if (value === '' || value === hyphenate(key)) {// only cast empty string / same name to boolean if// boolean has higher priorityconst stringIndex = getTypeIndex(String, prop.type)if (stringIndex < 0 || booleanIndex < stringIndex) {value = true}}}// check default valueif (value === undefined) {value = getPropDefaultValue(vm, prop, key)// since the default value is a fresh copy,// make sure to observe it.const prevShouldObserve = shouldObservetoggleObserving(true)observe(value)toggleObserving(prevShouldObserve)}if (process.env.NODE_ENV !== 'production' &&// skip validation for weex recycle-list child component props!(__WEEX__ && isObject(value) && ('@binding' in value))) {assertProp(prop, key, value, vm, absent)}return value
}
- 功能:验证单个
prop
的值,并处理默认值和类型转换。 - 参数:
key
:prop
的名称。propOptions
:prop
的选项对象。propsData
:传入的props
数据。vm
:可选的 Vue 实例。
- 步骤:
- 获取
prop
的选项和值,并检查是否缺失。 - 处理布尔类型的
prop
,如果缺失且没有默认值,将其设为false
;如果值为空字符串或与prop
名称相同,且布尔类型优先级更高,则将其设为true
。 - 如果值为
undefined
,则获取默认值,并确保默认值是响应式的。 - 在开发环境下,调用
assertProp
函数进行prop
验证。 - 返回验证后的值。
- 获取
3. getPropDefaultValue
函数
function getPropDefaultValue (vm: ?Component, prop: PropOptions, key: string): any {// no default, return undefinedif (!hasOwn(prop, 'default')) {return undefined}const def = prop.default// warn against non-factory defaults for Object & Arrayif (process.env.NODE_ENV !== 'production' && isObject(def)) {warn('Invalid default value for prop "' + key + '": ' +'Props with type Object/Array must use a factory function ' +'to return the default value.',vm)}// the raw prop value was also undefined from previous render,// return previous default value to avoid unnecessary watcher triggerif (vm && vm.$options.propsData &&vm.$options.propsData[key] === undefined &&vm._props[key] !== undefined) {return vm._props[key]}// call factory function for non-Function types// a value is Function if its prototype is function even across different execution contextreturn typeof def === 'function' && getType(prop.type) !== 'Function'? def.call(vm): def
}
- 功能:获取
prop
的默认值。 - 参数:
vm
:可选的 Vue 实例。prop
:prop
的选项对象。key
:prop
的名称。
- 步骤:
- 如果
prop
没有默认值,返回undefined
。 - 在开发环境下,如果默认值是对象或数组且不是工厂函数,发出警告。
- 如果上一次渲染时
prop
的值也是undefined
,返回上一次的默认值,以避免不必要的监听器触发。 - 如果默认值是函数且
prop
类型不是Function
,调用该函数并返回结果;否则,直接返回默认值。
- 如果
4. assertProp
函数
function assertProp (prop: PropOptions,name: string,value: any,vm: ?Component,absent: boolean
) {if (prop.required && absent) {warn('Missing required prop: "' + name + '"',vm)return}if (value == null && !prop.required) {return}let type = prop.typelet valid = !type || type === trueconst expectedTypes = []if (type) {if (!Array.isArray(type)) {type = [type]}for (let i = 0; i < type.length && !valid; i++) {const assertedType = assertType(value, type[i])expectedTypes.push(assertedType.expectedType || '')valid = assertedType.valid}}if (!valid) {warn(getInvalidTypeMessage(name, value, expectedTypes),vm)return}const validator = prop.validatorif (validator) {if (!validator(value)) {warn('Invalid prop: custom validator check failed for prop "' + name + '".',vm)}}
}
- 功能:断言
prop
是否有效。 - 参数:
prop
:prop
的选项对象。name
:prop
的名称。value
:prop
的值。vm
:可选的 Vue 实例。absent
:表示prop
是否缺失。
- 步骤:
- 如果
prop
是必需的但缺失,发出警告并返回。 - 如果
prop
不是必需的且值为null
或undefined
,直接返回。 - 检查
prop
的类型是否符合预期,如果不符合,发出警告。 - 如果
prop
有自定义验证函数,调用该函数进行验证,如果验证失败,发出警告。
- 如果
5. assertType
函数
const simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/function assertType (value: any, type: Function): {valid: boolean;expectedType: string;
} {let validconst expectedType = getType(type)if (simpleCheckRE.test(expectedType)) {const t = typeof valuevalid = t === expectedType.toLowerCase()// for primitive wrapper objectsif (!valid && t === 'object') {valid = value instanceof type}} else if (expectedType === 'Object') {valid = isPlainObject(value)} else if (expectedType === 'Array') {valid = Array.isArray(value)} else {valid = value instanceof type}return {valid,expectedType}
}
- 功能:检查值的类型是否符合预期。
- 参数:
value
:要检查的值。type
:预期的类型。
- 步骤:
- 获取预期类型的名称。
- 如果预期类型是简单类型(
String
、Number
、Boolean
、Function
、Symbol
),检查值的类型是否匹配;如果不匹配且值是对象,检查是否是该类型的实例。 - 如果预期类型是
Object
,检查值是否是普通对象。 - 如果预期类型是
Array
,检查值是否是数组。 - 对于其他类型,检查值是否是该类型的实例。
- 返回检查结果和预期类型名称。
6. 其他辅助函数
function getType (fn) {const match = fn && fn.toString().match(/^\s*function (\w+)/)return match ? match[1] : ''
}function isSameType (a, b) {return getType(a) === getType(b)
}function getTypeIndex (type, expectedTypes): number {if (!Array.isArray(expectedTypes)) {return isSameType(expectedTypes, type) ? 0 : -1}for (let i = 0, len = expectedTypes.length; i < len; i++) {if (isSameType(expectedTypes[i], type)) {return i}}return -1
}function getInvalidTypeMessage (name, value, expectedTypes) {let message = `Invalid prop: type check failed for prop "${name}".` +` Expected ${expectedTypes.map(capitalize).join(', ')}`const expectedType = expectedTypes[0]const receivedType = toRawType(value)const expectedValue = styleValue(value, expectedType)const receivedValue = styleValue(value, receivedType)// check if we need to specify expected valueif (expectedTypes.length === 1 &&isExplicable(expectedType) &&!isBoolean(expectedType, receivedType)) {message += ` with value ${expectedValue}`}message += `, got ${receivedType} `// check if we need to specify received valueif (isExplicable(receivedType)) {message += `with value ${receivedValue}.`}return message
}function styleValue (value, type) {if (type === 'String') {return `"${value}"`} else if (type === 'Number') {return `${Number(value)}`} else {return `${value}`}
}function isExplicable (value) {const explicitTypes = ['string', 'number', 'boolean']return explicitTypes.some(elem => value.toLowerCase() === elem)
}function isBoolean (...args) {return args.some(elem => elem.toLowerCase() === 'boolean')
}
getType
:通过函数的字符串表示获取类型名称。isSameType
:检查两个值的类型是否相同。getTypeIndex
:获取类型在预期类型数组中的索引。getInvalidTypeMessage
:生成类型检查失败的错误信息。styleValue
:根据类型格式化值。isExplicable
:检查值的类型是否可明确表示。isBoolean
:检查值的类型是否为布尔类型。
实现原理总结
- 验证流程 :当组件接收到
props
时,validateProp
函数会对每个prop
进行验证。首先进行布尔类型转换,然后处理默认值,最后在非生产环境下进行验证。 - 类型检查 :
assertType
函数负责检查值的类型是否符合要求,根据不同的类型使用不同的检查方法。 - 默认值处理 :
getPropDefaultValue
函数负责获取prop
的默认值,并处理非工厂函数的默认值警告。 - 自定义验证 :如果
prop
定义了自定义验证函数,则在assertProp
函数中调用该函数进行验证。
通过这些函数的协作,Vue
实现了对 props
的验证和处理,确保组件接收到的 props
符合定义要求。