认识
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
需要关注两部分:
-
vnode.props
: 为组件传递的props
数据 -
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
}
}
三、组件挂载细节
组件挂载 时, 需要解析 props
与 attrs
。
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];
}
四、组件更新细节
父组件更新时所引起子组件的更新叫作子组件的被动更新, 当子组件发生被动更新时, 我们需要做以下逻辑:
-
检测子组件是否需要更新, 因为子组件的
props
可能没有发生变化 -
如果需要更新, 则更新子组件的
props
、slots
等内容
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;
}