最近都在写Vue相关的文章,感兴趣的能够看回我以前写的。前端
props
初始化initProps
是如何运行的: vue
normalizeProps
: initProps
以前的规范化数据normalizeProps
的代码有点长,这里只列举通过规范化后的prop
类型和结果vue-cli
props: ["data"]
// 规范化后
props: {
data:{
type: null
}
}
复制代码
props: {
data1: {
type: String,
default: ''
}
data2: Number,
}
// 规范化后
props: {
data1: {
type: String,
default: ''
},
data2: {
type: Number
},
}
复制代码
initProps
: 处理props
源码分析以下:bash
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)
}
复制代码
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
,若无则为根节点if (!isRoot) {
toggleObserving(false)
}
for (const key in propsOptions) {
// 省略...
}
toggleObserving(true)
复制代码
!isRoot
:若当前实例非根节点,关闭toggleObserving
toggleObserving
: 能够理解为数据观测的开关for...in
: 遍历propsOptions
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值)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骚操做post
defineReactive
: 最终处理defineReactive(props, key, value)
复制代码
defineReactive
是老熟人了,但这里要注意一点: 先前toggleObserving(false)
,关闭了观测的开关,因此defineReactive
中调用 observe
, 是一个无效调用。学习
此时到这里,能够得出一个结论
props
是经过 defineReactive
定义的,此时虽然是响应式数据,但没有进行深度定义。
即,父组件传给子组件props后,子组件没必要再重复观测props
toggleObserving(true)
复制代码
从新打开观测开关,避免影响后续代码执行。
目前本人在准备跳槽,但愿各位大佬和HR小姐姐能够内推一份靠谱的深圳前端岗位!
huab119
454274033@qq.com