• Vue3 - $attrs 的几种用法(1个或多个根元素、Options API 和 Composition API)


    本文简介

    点赞 + 关注 + 收藏 = 学会了


    使用 Vue 开发时,肯定会接触到 组件 的概念,无可避免的也会接触到 组件通讯 的概念。

    组件通讯的方式有很多种,我在 《Vue3 过10种组件通讯方式》 一文中粗略罗列了 Vue3 常用的组件通讯方法。


    Vue 2 中除了 $attrs 外,还有 $listenersVue 3$listeners 合并到 $attrs 里了。

    而本文的重点是讲解在 Vue 3 中如何使用 $attrs

    本文使用的 Vue 版本是 3.2.25


    本文关键字:

    • $attrs:在 template 中使用(单一根元素和多个根元素的情况)
    • useAttrs:在 js 中使用(1种 Options API 和 2种 Composition API 的用法)


    attrs的作用

    在讲解 attrs 之前,你首先要知道组件常用的通讯方式:propsemits ,这两个是 Vue 组件通讯的基础,本文不会讲解。


    简单来说, attrs 主要接收没在 props 里定义,但父组件又传过来的属性。

    举个例子

    <!-- 父组件 ParentCom.vue -->
    <template>
      <ChildCom
        msg="雷猴"
        data="123"
      />
    </template>
    
    <script setup>
    import ChildCom from './ChildCom.vue'
    </script>
    
    
    
    <!-- 子组件 ChildCom.vue -->
    <template>
      <div>
        {{ msg }} - {{ $attrs }}
      </div>
    </template>
    
    <script setup>
    defineProps({
      msg: {
        type: String
      }
    })
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    file

    可以看到,在子组件中,msg 使用了 props 接收,所以 {{ msg }} 可以直接输出 props 里接收的内容。

    而没在 props 里接收的内容,全部都放到了 $attrs 里,并且存在一个对象里面。


    接下来将展开讲解不同情况下 attrs 的使用方法。



    attrs在 template 中的用法

    在前面简单的例子里其实已经大概知道 attrstemplate 的用法。但 Vue3template 不再要求只有一个根元素了。所以 attrstemplate 中分2种情况使用。


    只有1个根元素的情况下

    只有1个根元素的情况下,子组件中,没被 props 接收的属性,都会绑定在根元素上。

    <!-- 父组件 ParentCom.vue -->
    <template>
      <ChildCom
        msg="雷猴"
        data="123"
        name="鲨鱼辣椒"
        style="color: red;"
      />
    </template>
    
    <script setup>
    import ChildCom from './ChildCom.vue'
    </script>
    
    
    
    <!-- 子组件 ChildCom.vue -->
    <template>
      <div>
        {{ msg }}
      </div>
    </template>
    
    <script setup>
    defineProps({
      msg: {
        type: String
      }
    })
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    file

    可以看到,没被 props 接收的属性都被绑定到根元素上了。

    style 里传入的样式也被执行,文字变成红色了。


    如果此时我们想在页面输出 name 的值,可以在子组件中这样操作

    <!-- 这里省略 父组件代码 ...... -->
    
    
    
    <!-- 子组件 ChildCom.vue -->
    <template>
      <div>
        {{ $attrs.name }}
      </div>
    </template>
    
    <script setup>
    defineProps({
      msg: {
        type: String
      }
    })
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    file

    使用 $attrs.xxx ,这里的 xxx 是对应的属性名。


    有2个根元素的情况下

    当子组件有2个根元素时,没被 props 接收的属性不会绑定到子组件的元素上。

    <!-- 父组件 ParentCom.vue -->
    <template>
      <ChildCom
        msg="雷猴"
        data="123"
        name="鲨鱼辣椒"
        style="color: red;"
      />
    </template>
    
    <script setup>
    import ChildCom from './ChildCom.vue'
    </script>
    
    
    
    <!-- 子组件 ChildCom.vue -->
    <template>
      <div>
        {{ msg }}
      </div>
      <div>
        {{ msg }}
      </div>
    </template>
    
    <script setup>
    defineProps({
      msg: {
        type: String
      }
    })
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    file

    此时连父组件传入是 style 样式都不生效了。

    如果我们此时希望第二个元素绑定所有没被 props 接收的属性,可以使用 v-bind="$attrs" 的方法实现

    <!-- 父组件 ParentCom.vue -->
    <template>
      <ChildCom
        msg="雷猴"
        data="123"
        name="鲨鱼辣椒"
        style="color: red;"
      />
    </template>
    
    <script setup>
    import ChildCom from './ChildCom.vue'
    </script>
    
    
    
    <!-- 子组件 ChildCom.vue -->
    <template>
      <div>
        {{ msg }}
      </div>
      <div v-bind="$attrs">
        {{ msg }}
      </div>
    </template>
    
    <script setup>
    defineProps({
      msg: {
        type: String
      }
    })
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    file

    注意第二个元素,使用了 v-bind="$attrs" 绑定了所有没被 props 接收的属性。


    如果只希望绑定部分属性,可以单独写

    <!-- 这里省略 父组件代码 ...... -->
    
    
    
    <!-- 子组件 ChildCom.vue -->
    <template>
      <div>
        {{ msg }}
      </div>
      <div :style="$attrs.style">
        {{ msg }}
      </div>
    </template>
    
    <script setup>
    defineProps({
      msg: {
        type: String
      }
    })
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    file



    attrs在 js 中的用法

    除了在 template 中可以访问到 $attrs ,在 JS 中也可以访问到。


    vue 3 其实是兼容大部分 Vue 2 语法的,也就是 Options API 。而 attrsOptions APiComposition Api 中的使用方法会稍微有一丢丢区别。而 Composition API 又分为 Vue 3.2 前的语法和 3.2 后的语法。

    接下来将分开讨论这3种情况。


    Options API

    <!-- 父组件 ParentCom.vue -->
    <template>
      <ChildCom
        msg="雷猴"
        data="123"
        name="鲨鱼辣椒"
        style="color: red;"
      />
    </template>
    
    <script setup>
    import ChildCom from './ChildCom.vue'
    </script>
    
    
    
    <!-- 子组件 ChildCom.vue 暂不关注 template 部分 -->
    <script>
    export default {
      props: {
        msg: {
          type: String
        }
      },
      mounted() {
        console.log(this.$attrs)
      }
    }
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    file

    此时控制台会输出没被 props 接收的属性。


    Composition API 3.0的语法

    <!-- 父组件 ParentCom.vue -->
    <template>
      <ChildCom
        msg="雷猴"
        data="123"
        name="鲨鱼辣椒"
        style="color: red;"
      />
    </template>
    
    <script setup>
    import ChildCom from './ChildCom.vue'
    </script>
    
    
    
    <!-- 子组件 ChildCom.vue 暂不关注 template 部分 -->
    <script>
    export default {
      props: {
        msg: {
          type: String
        }
      },
      setup(props, context) {
        console.log('props: ', props)
        console.log('attrs: ', context.attrs)
      }
    }
    </script>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    file

    Vue 3.2 前的写法,需要在 setup 方法里接收2个参数,而 attrs 就在 context 参数里。


    Composition API 3.2的语法

    Vue 3.2 后的语法,可以在 <script> 标签上添加 setup 属性。所以在代码里就不需要再调用 setup 方法了。

    在这种情况下,props 成了默认的全局方法,而 attrs 则需要另外引入。

    <!-- 父组件 ParentCom.vue -->
    <template>
      <ChildCom
        msg="雷猴"
        data="123"
        name="鲨鱼辣椒"
        style="color: red;"
      />
    </template>
    
    <script setup>
    import ChildCom from './ChildCom.vue'
    </script>
    
    
    
    <!-- 子组件 ChildCom.vue 暂不关注 template 部分 -->
    <script setup>
    import { useAttrs } from 'vue'
    
    const props = defineProps({
      msg: {
        type: String
      }
    })
    
    const attrs = useAttrs()
    
    console.log('props: ', props)
    console.log('attrs: ', attrs)
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    file


    需要引入 vue 中的 useAttrs ,在调用 useAttrs 后会返回当前未被 props 接收的属性。

    重点是以下两句。

    import { useAttrs } from 'vue'
    const attrs = useAttrs()
    
    • 1
    • 2

    之后在 js 代码里就可以使用 attrs.xxx 获取对应的属性值了。



    推荐阅读

    👍《Vue3 过10种组件通讯方式》

    👍《vite vue3 如何在 js 中使用 scss 变量?》

    👍《『uni-app』web-view 大量数据通信》 点赞 + 关注 + 收藏 = 学会了

  • 相关阅读:
    【4. 操作系统—非连续内存分配】
    sklearn.preprocessing.StandardScaler¶
    数据结构第一章:部分答案
    C#项目怎么在IIS发布—教程图解
    走近高德驾车ETA(预估到达时间)
    webScoket长连接人性化解读
    Java工具库Guava的数学运算常用方法示例代码
    获取对象占用内存
    《性能之巅》学习笔记
    .Net服务器性能监控,应用耗时统一监控平台
  • 原文地址:https://blog.csdn.net/weixin_39415598/article/details/125440497