Vue mergeProps用法详细讲解

 更新时间:2022年10月24日 15:19:30   作者:cyg_l02  
这篇文章主要介绍了Vue mergeProps用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

很多人不知道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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue3+element Plus实现表格前端分页完整示例

    vue3+element Plus实现表格前端分页完整示例

    这篇文章主要给大家介绍了关于vue3+element Plus实现表格前端分页的相关资料,虽然很多时候后端会把分页,搜索,排序都做好,但是有些返回数据并不多的页面,或者其他原因不能后端分页的通常会前端处理,需要的朋友可以参考下
    2023-08-08
  • 写给vue新手们的vue渲染页面教程

    写给vue新手们的vue渲染页面教程

    这篇文章主要给大家分享了一个写给vue新手看的vue渲染页面教程,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,感兴趣的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • 详解vue axios二次封装

    详解vue axios二次封装

    这篇文章给大家分享了vue axios二次封装的相关知识点等内容以及实例代码,有兴趣的朋友可以参考学习下。
    2018-07-07
  • 解决$store.getters调用不执行的问题

    解决$store.getters调用不执行的问题

    今天小编就为大家分享一篇解决$store.getters调用不执行的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue.js如何在网页中实现一个金属抛光质感的按钮

    vue.js如何在网页中实现一个金属抛光质感的按钮

    这篇文章主要给大家介绍了关于vue.js如何在网页中实现一个金属抛光质感的按钮的相关资料,文中给出了详细的实例代码以及图文将实现的方法介绍的非常详细,需要的朋友可以参考下
    2023-04-04
  • Nginx配置Vue项目,无法按路径跳转及刷新404的解决方案

    Nginx配置Vue项目,无法按路径跳转及刷新404的解决方案

    这篇文章主要介绍了Nginx配置Vue项目,无法按路径跳转及刷新404的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Vue3项目中的hooks的使用教程

    Vue3项目中的hooks的使用教程

    今天我们稍微说一下 vue3 项目中的 hooks 的使用,其实这个 hooks 呢是和 vue2 当中的 mixin 是类似的,学习过 vue2 的小伙伴一定对 mixin 一定比较熟悉,快跟随小编一起来学习学习吧
    2022-08-08
  • Vue-Router进阶之滚动行为详解

    Vue-Router进阶之滚动行为详解

    本篇文章主要介绍了Vue-Router进阶之滚动行为详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 解决vue-loader加载不上的问题

    解决vue-loader加载不上的问题

    这篇文章主要介绍了解决vue-loader加载不上的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-10-10
  • 详解Vue如何在页面刷新时进行重定向

    详解Vue如何在页面刷新时进行重定向

    这篇文章主要为大家详细介绍了Vue如何在页面刷新时进行重定向,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2025-01-01

最新评论