Vue3: 透传的说明 + Props和 Attrs的区别

题外话:Vue 接触的很早从最早的vue1开始,那时候也拿来做了些apps,但是也是很早就放弃了然后一直深耕在React上.当时的种种考虑中有一点就是vue太不稳定了(版本上)其实也很明智.但是这些都不妨碍Vue是最流行和高效的前端框架之一的地位.现在招聘和项目vue占的比重一直都是很大的. 前阵子Vue3出来了.准备学习下Vue3. 期望这次的版本能稳定一段时间吧.至少别整个vue4,5然后大变样.

 1.什么是透传

 其实当我看到这次个词的第一印象就是props的值传递.但是这其实太小看vue了.

“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 classstyle 和 id

官方的解释其实很通透.只不过是在我理解完透传以后再回头看这句话. 不看代码单纯从这个词来理解就很好理解,直接让值穿透到子组件上.而且Vue比较牛的是.这个透传是自动设置到组件的元素上(如果没有指定,下面会说到). 

2. 自动透传
 


<script setup lang="ts">
// 引入子组件
import Com from './com1.vue'

interface Props {
  msg?: string;
}
defineProps<Props>();

// 需要透传的函数
 function handleOnClick () {
    console.log("success")
}

</script>
<template>
    {{ msg }}

/*
* 这里透传了2个属性值
* handleOnClick: 一个v-on的函数
* message: 这个是props,不是透传 注意不要弄混
* class: 这个是我们需要透传的class
**/

    <Com @click="handleOnClick" message="Evan" class="fontRed"> click me </Com>
</template>
<style >
/**
* 透传的class
*/
    .fontRed {
        color: red;
    }
</style>

 子组件: com1.vue

<script setup lang="ts">
    interface Prop {
        message?: string;
    }
    defineProps<Prop>()
</script>

<template >
  <div>{{message}} -- 这个值是props 传递的值,但是颜色是透传过来的</div>
</template>

运行后结果
 可以看到点击后的控制台输入了透传过来的函数.这个自动透传真的有点意思.

当然实际项目中很少有一个组件就一个dom节点的存在,那透传怎么能对应到自己想要的节点上呢.

3.指定透传

使用 

    defineOptions({
        inheritAttrs: false,
    })

并且配合 $attrs

修改下子组件如下

 

<script setup lang="ts">
    interface Prop {
        message?: string;
    }
     defineProps<Prop>()
    defineOptions({
        inheritAttrs: false,
    })

</script>

<template >
// 指定div的click event 获取透传的函数
<div @click="$attrs.onClick" >{{message}} -- 这个值是props 传递的值,但是颜色是透传过来的</div>
// 指定button元素的class获取透传的class
<button :class="$attrs.class">
    <slot></slot>
</button>
</template>

效果如下

4.爷孙组件透传

其实官网的介绍也就到这里了.但是在实际项目中我们的组件深度往往不仅限于这2层,再加一个孙子组件透传怎么传呢?
其实很简单v-bind:$attrs 透传绑定到孙子组件

首先来个简单的孙子组件

<script setup lang="ts">
    interface Prop {
        test?: string;
    }
    defineProps<Prop>()
</script>

<template >

<div >{{test}} -- 透传过来变成红色字体了</div>
</template>

修改儿子组件

<script setup lang="ts">
// 引入孙子组件
import ComA from './com2.vue'
    interface Prop {
        message?: string;
    }
     defineProps<Prop>()
    defineOptions({
        inheritAttrs: false,
    })

</script>

<template >

<div  >{{message}} </div>
<button>
    <slot></slot>
</button>
// 透传属性到孙子节点
<ComA v-bind="$attrs"/>
</template>

运行下看效果

可以看到透传成功到了孙子组件 

官方还提供了一个useAttrs 函数可以在js代码中访问一个组件所有透传的属性
 

import {useAttrs} from 'vue'

const attrs = useAttrs()

console.log(attrs)

5. attrs的特点


说了半天透传 总结下透传的特别
attrs:
定义上:attrs($attrs)是一个对象,包含传递给组件的所有未明确声明为道具的属性和监听器。
使用方法 对于属性转发非常有用,尤其是在创建高阶组件或包装组件时,你需要将属性传递给子元素或组件。
自动继承: 未定义为透传的属性会自动添加到组件的根元素中。
没有验证:attrs 不提供验证或默认值。
静态性:attrs 不是响应性的,不能像props一样跟踪它的变化。

6. props的不同

声明: props: 必须在子组件中明确声明。
            Attrs: 自动包含传递给组件的所有非props属性。

使用方法    Props: 用于传递特定数据和处理程序。
                  Attrs: 用于传递任意属性和监听器。

验证和默认值:props: 可以有类型、默认值和验证器。
                        Attrs: 不提供验证或默认值。

响应性 props: 具有反应性,在父节点更新时更新。
           attrs: 本质上不是反应式的,但可在反应式上下文中使用。

总结下:


Attrs给我的感觉更像是一个对props, emit的补充. 不像React在类似透传中使用{...props} 这样随便丢过去或者直接uesReducer, useContext这么复杂,vue的透传是很有目的性的.传递+赋值书写起来很流畅,需要注意的是:如果父组件传递了一个方法,但是子组件忘记使用或者指定分配而被透传自动分配.这样还是比较麻烦的

### Vue3 中 `v-bind` 与 `$attrs` 的使用方法差异 #### 组件属性递机制概述 在 Vue3 中,组件之间的属性递变得更加灵活。通过组合使用 `v-bind` `$attrs` 可以实现更复杂的父子组件间的数据流动。 #### 属性继承控制 为了更好地管理父级递给子组件的属性,默认情况下未被显式声明为 prop 的属性会自动应用到根元素上。然而可以通过设置 `inheritAttrs: false` 来阻止这种行为[^1]。 #### 使用场景对比 当希望将所有非 Prop 类型的特性(attributes)至内部嵌套使用的另一个组件时,则应该采用如下形式: ```html <ChildComponent v-bind="$attrs"/> ``` 这表示将会把当前作用域内的所有剩余 attribute (即不是 props 的部分) 转交给 ChildComponent 实例处理[^4]。 如果只是单纯想要转发特定 Props 则应直接指定名称列表而不是整个对象: ```html <!-- 错误示范 --> <ChildComponent :someProp="value"/> <!-- 正确做法 --> <GrandchildComponent v-bind="{ someProp }"/> ``` 对于爷孙关系间的多层穿通讯而言,在中间层次可以选择性地利用上述两种方式之一来完成数据流转任务[^2]。 #### 关键代码示例 下面给出一段完整的 HTML 结构用于展示如何在一个三层结构的应用程序内运用这些概念: ```html <Father> <!-- 这里的 $attrs 将包含除 &#39;custom-prop&#39; 外的所有属性 --> <Son v-bind="$attrs" custom-prop="foo"> <!-- 子组件 Son 不再继续向下attrs,而是自行消费它们 --> <Grandson /> </Son> </Father> <script setup lang="ts"> import { defineProps } from &#39;vue&#39;; // 假设 Father 定义了一些额外的 props 或者事件监听器... defineProps({ // ... }); </script> ``` 在此基础上还可以进一步探索更多高级特性最佳实践模式,比如结合 TypeScript 提供更强类型的保障等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值