VUE-这回真的要彻底理解Vue选项Props

VUE-这回真的要彻底理解Vue选项Props1.normalizeProps: initProps 之前的规范化数据normalizeProps的代码有点长,这里只列举经过规范化后的prop类型和结果1.1 字符串props: [“data”] // 规范化后 p

大家好,欢迎来到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

VUE-这回真的要彻底理解Vue选项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

(0)
上一篇 2024-09-25 05:26
下一篇 2024-09-27 10:26

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信