vue push 无效_VUE-这回真的要彻底理解Vue选项Props

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

a1457e91419c21c846fa5ed178f537f3.png

源码分析如下:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值