很多人不知道megreProps的用法,今天我们就来讲解下mergeProps的用法以及原理

用法

大家觉得下面哪种用法是正确的呢?

这样

style: mergeProps({
width: this.itemWidth
}, xProps.style)

或者这样

style: mergeProps({
style: {
width: this.itemWidth
},
...(xProps?.style ?? {})
})

还是这样

style: mergeProps(
{
style: { width: this.itemWidth },
},
xProps,
).style

你使用的话会使用上面哪一种呢?

不知道

因为写的是jsx语法,所以查看了vue3的jsx语法,发现里面并没有关于这个解释,只说到了默认开启

于是去vue3官网查找,找到

megreProps:Merge multiple props objects with special handling for certain props.

意思就说合并多个道具对象,对某些道具进行特殊处理

所以前面两种写法是错误的

接着看了下mergeProps源码的写法

// ...args将多个对象收集成数组
export function mergeProps(...args: (Data & VNodeProps)[]) {
// 最终合并的结果
const ret: Data = {}
// 遍历用户传入的多个对象
for (let i = 0; i < args.length; i++) {
// 取到传入的对象值
const toMerge = args[i]
for (const key in toMerge) {
// 对class进行序列化合并处理
if (key === 'class') {
if (ret.class !== toMerge.class) {
ret.class = normalizeClass([ret.class, toMerge.class])
}
// 对style进行序列化合并处理
} else if (key === 'style') {
ret.style = normalizeStyle([ret.style, toMerge.style])
// 对其他的绑定的属性进行合并
} else if (isOn(key)) {
const existing = ret[key]
const incoming = toMerge[key]
if (
incoming &&
existing !== incoming &&
!(isArray(existing) && existing.includes(incoming))
) {
ret[key] = existing
? [].concat(existing as any, incoming as any)
: incoming
}
// 如果是普通元素上的用户自定义属性,则直接赋值
} else if (key !== '') {
ret[key] = toMerge[key]
}
}
}
return ret
}

所以你传入的对象里面是需要有style、class等key的

接下来看看normalizeClass这个方法,这个方法就是将用户写的多种格式(比如数组,对象,字符串)的class进行序列化成字符串给到最终渲染的元素

export function normalizeClass(value: unknown): string {
let res = ''
// 如果是字符串,直接返回
if (isString(value)) {
res = value
// 如果是数组
} else if (isArray(value)) {
for (let i = 0; i < value.length; i++) {
// 递归调用进行处理
const normalized = normalizeClass(value[i])
if (normalized) {
res += normalized + ' '
}
}
// 如果是对象, 如{ active: isActive, 'text-danger': hasError },需要把key拼接
} else if (isObject(value)) {
for (const name in value) {
if (value[name]) {
res += name + ' '
}
}
}
return res.trim()
}

再看看normalizeStyle这个函数

export type NormalizedStyle = Record<string, string | number>
export function normalizeStyle(
value: unknown
): NormalizedStyle | string | undefined {
// 如果是数组的情况
if (isArray(value)) {
const res: NormalizedStyle = {}
for (let i = 0; i < value.length; i++) {
const item = value[i]
const normalized = isString(item)
? parseStringStyle(item)
: (normalizeStyle(item) as NormalizedStyle)
if (normalized) {
// 将序列化后的style保存到ret上
for (const key in normalized) {
res[key] = normalized[key]
}
}
}
return res
} else if (isString(value)) {
return value
} else if (isObject(value)) {
return value
}
}

parseStringStyle函数就是将字符串对;进行分割,然后设置对应的key,value

元素上的style只能使用string,所以在最终挂在到dom元素上需要进行stringifyStyle

export function stringifyStyle(
styles: NormalizedStyle | string | undefined
): string {
let ret = ''
if (!styles || isString(styles)) {
return ret
}
for (const key in styles) {
const value = styles[key]
const normalizedKey = key.startsWith(`--`) ? key : hyphenate(key)
if (
isString(value) ||
(typeof value === 'number' && isNoUnitNumericStyleProp(normalizedKey))
) {
// only render valid values
ret += `${normalizedKey}:${value};`
}
}
return ret
}

所以通过简单的对vue3的mergeProps的代码进行简单分析就能知道其原理了,使用上也会更加的熟练

到此这篇关于Vue mergeProps用法详细讲解的文章就介绍到这了,更多相关Vue mergeProps内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。