Skip to content

一、属性传递(props和attrs)

先明确一下propsattrs区别:

用户在组件中声明的属性为props,用户没有声明的属性为attrs,比如:

ts
const Comp = {
    // 用户声明的属性
    props: {
        msg: String
    },
    render() {
        return h('div', 'hello world')
    }
}
createApp(Comp, { msg: 'hello world', count:0, }).mount('#app')

上面代码声明了msg属性,count属性是没有声明的属性,所以集体的propsattrs分别是

  • props: { msg: 'hello world'}
  • attrs: { count: 0 }

二、处理props和attrs的传递

处理传递的props

ts
/**
 * 创建组件实例
 */
export function createComponentInstance(vnode) {
    const { type } = vnode
    const instance = {
        // 省略部分代码
        // 将props进行标准化,不管是数组还是对象都转化为对象
        propsOptions: normalizePropsOptions(type.props)
    }
    return instance
}

packages/runtime-core/src/componentProps.ts 这个文件主要用处理props相关逻辑

ts
// componentProps.ts
export function normalizePropsOptions(props = {}) {
    if(isArray(props)) {
        return props.reduce((prev, cur) => {
            prev[cur] = {}
            return prev
        }, {})
    }
    return props
}
/**
 * 设置所有的props和attrs
 */
function setFullProps(instance, rawProps, props, attrs) {
    // 拿到 propsOptions
    const propsOptions = instance.propsOptions
    if(rawProps) {
        // 如果传递了props
        for(const key in rawProps) {
            if(hasOwn(propsOptions, key)) {
                // 如果 propsOptions 里面有这个 key,应该放到 props 里面
                props[key] = value
            } else {
                // 否则就是 attrs 里面的
                attrs[key] = value
            }
        }
    }
}

export function initProps(instance) {
    // 初始化 props
    const { vnode } = instance
    // 拿到用户使用组件时传递的 props
    const rawProps = vnode.props

    const props = {}
    const attrs = {}
    setFullProps(instance, rawProps, props, attrs)
    // props 是响应式的,所以需要 reactive
    instance.props = reactive(props)
    // attrs 不是响应式的
    instance.attrs = attrs
}

component.ts中的setupComponent函数中初始化props

ts
/**
 * 初始化组件
 */
export function setupComponent(instance) {
    /**
     * 初始化属性
     */
    const { type } = instance
    // 初始化prop
    initProps(instance)

    if(inFunction(type.setup)) {
        const setupResult = proxyRefs(type.setup(instance.props))
        // 拿到setup返回状态
        instance.setupState = setupResult
    }

    // 将render函数,绑定给instance
    instance.render = type.render
}

至此,propsattrs的传递就完成了。

Released under the MIT License.