跳到主要内容

认识

2023年06月10日
柏拉文
越努力,越幸运

一、认识


对于一个组件来说, 比如 <MyComponent a="xixi" b="哈哈"> , 转化成对应的 VNode 如下:

const MyComponent = {
name: 'MyComponent',
props: {
a: String,
b: String,
},
data(){
return {

}
}
}

const vnode = {
type: MyComponent,
props: {
a: 'xixi',
b: '哈哈'
}
}

因此, 组件Props 需要关注两部分:

  1. vnode.props: 为组件传递的 props 数据

  2. vnode.type.props: 组件选项定义的 props 选项。在 vnode.type.props 中显示声明的 key 会存储到 props 中, 没有在 vnode.type.props 中显示声明的 key 会存储到 attrs 中。

二、编译细节


模版组件如下所示:

<MyComponent a="嘻嘻" @handleChange="handleChange"></MyComponent>

模版编译的渲染函数如下:

模版最终生成的 VNode 如下所示:

const MyComponent = {
name: 'MyComponent',
data(){
return {

}
},
setup(){

},
render(){
return {
type: 'div',
children: ''
}
}
}

const vnode = {
type: MyComponent,
props: {
a: '嘻嘻',
onHandleChange: handleChange
}
}

三、组件挂载细节


组件挂载 时, 需要解析 propsattrs

3.1 解析 Props

export function resolveProps(options, propsData) {
const props = {};
const attrs = {};
for (const key in propsData) {
if (key in options) {
// 如果 key 在 vnode.type.props 有定义,存储到 props 中
props[key] = propsData[key];
} else {
// 如果 key 在 vnode.type.props 没有定义, 存储到 attrs 中
attrs[key] = propsData[key];
}
}
return [props, attrs];
}

四、组件更新细节


父组件更新时所引起子组件的更新叫作子组件的被动更新, 当子组件发生被动更新时, 我们需要做以下逻辑:

  1. 检测子组件是否需要更新, 因为子组件的 props 可能没有发生变化

  2. 如果需要更新, 则更新子组件的 propsslots 等内容

4.1 对比 Props

export function hasPropsChanged(prevProps, nextProps) {
const nextKeys = Object.keys(nextProps);
if (nextKeys.length !== Object.keys(prevPorps).length) {
return true;
}
for (let i = 0; i < nextKeys.length; i++) {
const key = nextKeys[i];
if (nextProps[key] !== prevProps[key]) {
return true;
}
}
return false;
}