- props支持对象和数组两种,二选一,否则给出警告
- props中数组定义必须是字符串,否则给出警告
- 不管数组还是对象把key转换成驼峰处理,如('my-component'转成myComponent)等
- 使用缓存对象保存处理后的驼峰结果,不用每次都去调用方法
源码片断
/**
* @author: SM
* Vue中props处理
*/
// 是否包含-连接
var camelizeRE = /-(\w)/g;
// 按照-分割并且首个字符转换成大写,并返回驼峰后的结果
var camelize = cached(function (str) {
return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })
});
// Object toString方法
var _toString = Object.prototype.toString;
// value对应的值
function toRawType (value) {
return _toString.call(value).slice(8, -1)
}
/**
* 判断是否对象
* @param {*} obj
* @returns
*/
function isPlainObject (obj) {
return _toString.call(obj) === '[object Object]'
}
/**
* 缓存对象
*/
function cached (fn) {
// 创建空对象
var cache = Object.create(null);
//
return (function cachedFn (str) {
// props中每个key
var hit = cache[str];
// 如果缓存存在返回缓存中对应的key,如果没有返回处理驼峰后的值
// 只所以用缓存是为了不重复调用fn处理
return hit || (cache[str] = fn(str))
})
}
/**
* Ensure all props option syntax are normalized into the
* Object-based format.
*/
function normalizeProps (options, vm) {
// 获取props对象
var props = options.props;
// 如果没有定义props则退出
if (!props) { return }
// 接受处理后的options
var res = {};
var i, val, name;
// 如果是数组
if (Array.isArray(props)) {
i = props.length;
while (i--) {
val = props[i];
// 数组中每项值必须是字符串
if (typeof val === 'string') {
// 处理成驼峰返回
name = camelize(val);
res[name] = { type: null };
} else {
// 使用数组语法时,props必须是字符串
console.log('props must be strings when using array syntax.');
}
}
} else if (isPlainObject(props)) { // 如果是对象,vue中props大多以对象方式定义
for (var key in props) {
// 获取value
val = props[key];
// 获取转换后的key
name = camelize(key);
// 如果value是对象定义直接原样返回,否则返回value对应的类型
res[name] = isPlainObject(val) ? val : { type: val };
}
} else { // 什么都不是,给出警告,并且输出原始类型(要么数组、要么对象)
console.log(
"Invalid value for option \"props\": expected an Array or an Object, " +
"but got " + (toRawType(props)) + ".",
vm
);
}
// 更改props处理后的值
options.props = res;
}
// 定义props
let data = {
// 定义props
props: {
// 姓名
name: String,
// 用户信息
userInfo: {
type: Object
},
// 年龄
age: {
type: Number,
default: 20
},
// 爱好
hobby: Array,
// 爱好
occupation: {
type: Array,
default:()=>{return ['CEO', 'CTO' ]}
},
//
'last-user-name': String
}
}
// 1、对象调用方法处理
normalizeProps(data, this);
console.log('option ===', data);
// 2、数组处理
let data2 = {
// 定义props
props: ['tData', 'list', 'my-component']
}
normalizeProps(data2, this);
console.log('option2 ===', data2);
网友评论