前言
在初始化过程中initState主要负责初始化props、methods、data、computed与watch,此篇主要对props初始化的源码解析,避免太长,computed与watch篇会在另一篇文章解释。
data与methods的部分前面已有,
data导航:vue2.0源码解析,Data,
methods导航:vue2.0源码解析,Methods。
initState
// init.js
initState(vm);
// state.js
/*初始化props、methods、data、computed与watch*/
export function initState(vm: Component) {
// initState方法内其余除了initProps的代码都忽略掉
/*初始化props*/
if (opts.props) initProps(vm, opts.props);
}
/*初始化props*/
function initProps(vm: Component, propsOptions: Object) {
const propsData = vm.$options.propsData || {
};
const props = (vm._props = {
});
// cache prop keys so that future props updates can iterate using Array
// instead of dynamic object key enumeration.
/*缓存属性的key,使得将来能直接使用数组的索引值来更新props来替代动态地枚举对象*/
const keys = (vm.$options._propKeys = []);
/*根据$parent是否存在来判断当前是否是根结点*/
const isRoot = !vm.$parent;
// root instance props should be converted
/*根结点会给shouldConvert赋true,根结点的props应该被转换*/
observerState.shouldConvert = isRoot;
for (const key in propsOptions) {
/*props的key值存入keys(_propKeys)中*/
keys.push(key);
/*验证prop,不存在用默认值替换,类型为bool则声称true或false,当使用default中的默认值的时候会将默认值的副本进行observe*/
const value = validateProp(key, propsOptions, propsData, vm);
/* istanbul ignore else */
if (process.env.NODE_ENV !== 'production') {
/*判断是否是保留字段,如果是则发出warning*/
if (isReservedProp[key] || config.isReservedAttr(key)) {
warn(`"${
key}" is a reserved attribute and cannot be used as component prop.`, vm);
}
defineReactive(props, key, value, () => {
/*
由于父组件重新渲染的时候会重写prop的值,所以应该直接使用prop来作为一个data或者计算属性的依赖
https://cn.vuejs.org/v2/guide/components.html#字面量语法-vs-动态语法
*/
if (vm.$parent && !observerState.isSettingProps) {
warn(`Avoid mutating a prop directly since the value will be ` + `overwritten whenever the parent component re-renders. ` + `Instead, use a data or computed property based on the prop's ` + `value. Prop being mutated: "${
key}"`, vm);
}