大家好,欢迎来到IT知识分享网。
1.normalizeProps: initProps 之前的规范化数据
normalizeProps的代码有点长,这里只列举经过规范化后的prop类型和结果
1.1 字符串
props: ["data"] // 规范化后 props: { data:{ type: null } }
1.2 对象
props: { data1: { type: String, default: '' } data2: Number, } // 规范化后 props: { data1: { type: String, default: '' }, data2: { type: Number }, }
2.initProps: 处理props
源码分析如下:
function initProps (vm: Component, propsOptions: Object) { const propsData = vm.$options.propsData || {} const props = vm._props = {} const keys = vm.$options._propKeys = [] const isRoot = !vm.$parent if (!isRoot) { toggleObserving(false) } for (const key in propsOptions) { keys.push(key) const value = validateProp(key, propsOptions, propsData, vm) if (process.env.NODE_ENV !== 'production') { const hyphenatedKey = hyphenate(key) if (isReservedAttribute(hyphenatedKey) || config.isReservedAttr(hyphenatedKey)) { warn( `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`, vm ) } defineReactive(props, key, value, () => { if (!isRoot && !isUpdatingChildComponent) { warn( `Avoid mutating a prop direct....`, vm ) } }) } else { defineReactive(props, key, value) } if (!(key in vm)) { proxy(vm, `_props`, key) } } toggleObserving(true) }
2.1 常量定义
const propsData = vm.$options.propsData || {} const props = vm._props = {} const keys = vm.$options._propKeys = [] const isRoot = !vm.$parent
- propsData: 存储着传递进来的 props 的值
- props: 引用vm._props`,并初始化为{}
- keys: 在 vm.$options 上添加 _propKeys 属性
- isRoot: 判断是否存在vm.$parent,若无则为根节点
2.2 条件判断及循环
if (!isRoot) { toggleObserving(false) } for (const key in propsOptions) { // 省略... } toggleObserving(true)
- !isRoot:若当前实例非根节点,关闭toggleObserving
- toggleObserving: 可以理解为数据观测的开关
- for…in : 遍历propsOptions
2.2.1: 遍历propsOptions做什么
for (const key in propsOptions) { keys.push(key) const value = validateProp(key, propsOptions, propsData, vm) if (process.env.NODE_ENV !== 'production') { const hyphenatedKey = hyphenate(key) if (isReservedAttribute(hyphenatedKey) || config.isReservedAttr(hyphenatedKey)) { warn( `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`, vm ) } defineReactive(props, key, value, () => { if (!isRoot && !isUpdatingChildComponent) { warn( `Avoid mutating a prop directly since the value will be ` + `overwri tten whenever the parent component re-renders. ` + `Instead, use a data or computed property based on the prop's ` + `value. Prop being mutated: "${key}"`, vm ) } }) } else { defineReactive(props, key, value) } }
划重点:
- propsOptions 即opts.props
- key 就是每个 prop 的名字
此时进入循环:
keys.push(key) const value = validateProp(key, propsOptions, propsData, vm)
- 将 key 添加到 vm.$options._propKeys
- value: 用validateProp校验是否为预期的类型值,然后返回相应 prop 值(或default值)
2.2.2: 接着进入 if…else:
这里注释一下:
if (process.env.NODE_ENV !== 'production') { // 驼峰转连字符 const hyphenatedKey = hyphenate(key) // 校验prop是否为内置的属性 // 内置属性:key,ref,slot,slot-scope,is if (isReservedAttribute(hyphenatedKey) || config.isReservedAttr(hyphenatedKey)) { warn( `"${hyphenatedKey}" is a reserved attribute and cannot be used as component prop.`, vm ) } defineReactive(props, key, value, () => { // 子组件直接修改属性时 弹出警告 if (!isRoot && !isUpdatingChildComponent) { warn( `Avoid mutating a prop directly since the value will be ` + `overwri tten whenever the parent component re-renders. ` + `Instead, use a data or computed property based on the prop's ` + `value. Prop being mutated: "${key}"`, vm ) } }) } else { defineReactive(props, key, value) }
最后简化:
if (process.env.NODE_ENV !== 'production') { // 驼峰转连字符 // 校验prop是否为内置的属性 // 内置属性:key,ref,slot,slot-scope,is // 若是内置,弹出警告 defineReactive(props, key, value, () => { // 子组件直接修改属性时 弹出警告 } else { defineReactive(props, key, value) }
工具函数: 「从源码中学习」Vue源码中的JS骚操作
2.2.3: defineReactive: 最终处理
defineReactive(props, key, value)
defineReactive是老熟人了,但这里要注意一点: 先前toggleObserving(false),关闭了观测的开关,所以defineReactive中调用 observe, 是一个无效调用。
此时到这里,可以得出一个结论
props 是通过 defineReactive定义的,此时虽然是响应式数据,但没有进行深度定义。
即,父组件传给子组件props后,子组件不必再重复观测props
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/85389.html