自我介绍:大家好,我是吉帅振的网络日志;微信公众号:吉帅振的网络日志;前端开发工程师,工作4年,去过上海、北京,经历创业公司,进过大厂,现在郑州敲代码。
一、前言
页面可以由一个个组件构建而成,组件是一种抽象的概念,它是对页面的部分布局和逻辑的封装。为了让组件支持各种丰富的功能,Vue.js 设计了 Props 特性,它允许组件的使用者在外部传递 Props,然后组件内部就可以根据这些 Props 去实现各种各样的功能。
二、Props 的初始化
function setupComponent (instance, isSSR = false) {
const { props, children, shapeFlag } = instance.vnode
// 判断是否是一个有状态的组件
const isStateful = shapeFlag & 4
// 初始化 props
initProps(instance, props, isStateful, isSSR)
// 初始化插槽
initSlots(instance, children)
// 设置有状态的组件实例
const setupResult = isStateful
? setupStatefulComponent(instance, isSSR)
: undefined
return setupResult
}
function initProps(instance, rawProps, isStateful, isSSR = false) {
const props = {}
const attrs = {}
def(attrs, InternalObjectKey, 1)
// 设置 props 的值
setFullProps(instance, rawProps, props, attrs)
// 验证 props 合法
if ((process.env.NODE_ENV !== 'production')) {
validateProps(props, instance.type)
}
if (isStateful) {
// 有状态组件,响应式处理
instance.props = isSSR ? props : shallowReactive(props)
}
else {
// 函数式组件处理
if (!instance.type.props) {
instance.props = attrs
}
else {
instance.props = props
}
}
// 普通属性赋值
instance.attrs = attrs
}
初始化 Props 主要做了以下几件事情:设置 props 的值,验证 props 是否合法,把 props 变成响应式,以及添加到实例 instance.props 上。
1.设置 Props
function setFullProps(instance, rawProps, props, attrs) {
// 标准化 props 的配置
const [options, needCastKeys] = normalizePropsOptions(instance.type)
if (rawProps) {
for (const key in rawProps) {
const value = rawProps[key]
// 一些保留的 prop 比如 ref、key 是不会传递的
if (isReservedProp(key)) {
continue
}
// 连字符形式的 props 也转成驼峰形式
let camelKey
if (options && hasOwn(options, (camelKey = camelize(key)))) {
props[camelKey] = value
}
else if (!isEmitListener(instance.type, key)) {
// 非事件派发相关的,且不在 props 中定义的普通属性用 attrs 保留
attrs[key] = value
}
}
}
if (needCastKeys) {
// 需要做转换的 props
const rawCurrentProps = toRaw(props)
for (let i = 0; i < needCastKeys.length; i+