一文搞懂Vue3中的透传属性

8,721 阅读2分钟

透传属性

在Vue3中有一个很有意思的特性,透传属性。透传又分为自动透传绑定,和手动绑定两种。

什么是透传属性? 透传属性指组件在使用的时候,作用在组件上的属性,会被向下流动,绑定到组件内的标签中。

什么属性可以透传? classidstyle,属性,事件等头可以透传到组件内的标签中。(前提是属性和事件没有在组件中定义,后面会介绍)

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第5天,点击查看活动详情

1.自动透传绑定

如果组件中只有一个根标签,那么在父组件上使用的时候,给组件绑定的属性(属性,class,style,事件等)就会自动透传绑定到该组件的根标签上。

子组件中:

<template>
   <div>232222</div>
</template>

父组件中:

<hello-world class="item" cat="cat1"></hello-world>

最终会渲染成

<div class="item" cat="cat1">232222</div>

2. 手动绑定透传属性

上面说的是单根标签组件的情况,那如果一个组件有多个根标签节点呢?

一个组件如果拥有多个根标签节点,那么就不会有自动透传绑定属性的行为,因为Vue不知道给哪个根标签绑定透传属性,这就需要我们手动去绑定透传属性。

父组件中:

<hello-world class="item" :cat="person.name" ></hello-world>

子组件:通过 v-bind="$attrs"来手动给一个标签绑定透传属性。

<template>
   <div>23332</div>
   <div v-bind="$attrs">26662</div>
</template>

最终渲染结果:

<div>23332</div>
<div class="item" cat="cat">26662</div>

手动绑定透传属性,是可以绑定给任意的标签元素的,并且是可以绑定给多个标签元素

   <div v-bind="$attrs">23332</div>
   <div>
      26662
      <div v-bind="$attrs">27772</div>
      <div v-bind="$attrs">28882</div>
   </div>

3. 关闭自动透传行为

上面提到过,一个组件是单根标签组件,那么透传的属性是会默认自动绑定给根标签元素的。如果我们不想透传属性绑定给我们的根标签,而是我们手动指定绑定给哪个标签呢?

我们可以在组件内通过 inheritAttrs: false来关闭组件默认自动绑定行为

如果你使用了 <script setup>,你需要一个额外的 <script> 块来书写这个选项声明:

关闭默认的自动绑定行为:

<script>
// 使用一个简单的 <script> to declare options
export default {
  inheritAttrs: false//关闭默认绑定行为。
}
</script>

<script setup>
// ...setup 部分逻辑
</script>

手动绑定透传属性:通过v-bind="$attrs"手动给标签绑定透传属性:

<div>
   <div v-bind="$attrs">23332</div>
</div>

父组件中传入:

<hello-world class="item" :cat="person.name" ></hello-world>

上面的代码会被渲染成:

<div>
   <div class="item" cat="cat">23332</div>
</div>

4.透传属性和props

传入一个属性或者是事件,如果这个属性、事件没有在组件中定义,那么它依然是透传属性,因为没有东西接受它。

如果是事先定义了defineEmitsdefineProps来接受它,那么它就是props属性或自定义事件,不再是透传属性。

总之一句话:如果这个属性事件,没有再组件中定义,那么它就是透传属性,反之则不是。

子组件中:

defineProps<{
   title: string
}>()

父组件:

<hello-world class="item" cat="cat1" title="标题"></hello-world>

最终会渲染成:

<div class="item" cat="cat1">232222</div>

可以看到title属性并没有在标签上,而是传给了props的title (事件也是同理,不在举例)

6.获取透传属性

在模板中通过$attrs对象来使用透传属性,在代码中通过useAttrs()api来获取到透传对象,然后使用。通过透传对象可以获取透传过来的 class,style,id,事件和属性等。

模板中:

<div>{{ $attrs }}</div>

代码中:

const attrs = useAttrs();
console.log(attrs);

争议点:

​ 在Vue官网文档中说attrs对象并不是一个响应式对象,不能使用侦听器。但是打印出来的attrs对象确实是一个proxy的代理对象,并且也是使用计算属性,侦听器。

7.总结

  • 什么是透传属性:

    • 作用在组件上的属性(class,id,style,属性,事件)会被向下流动,作用组件的标签上。这些属性就是透传属性。
    • 如果这个属性或事件,没有在组件中定义,那么它就是透传属性,反之则不是。
  • 使用透传属性:

    • 在模板中通过$attrs对象来使用透传属性,在代码中通过useAttrs()api来获取到透传对象,然后使用
  • 透传分为自动透传和手动绑定两种:

    • 自动透传:在只有一个根标签的组件中,作用在组件上的属性会默认自动透传绑定到该组件的根标签上。
    • 手动绑定:在拥有多个根标签的组件中,是没有默认的自动透传绑定的,因为Vue不知道绑定给哪个根标签,需要我们手动去绑定。
    • 手动绑定透传属性,是可以绑定任意的标签元素的,并且可以绑定给多个。
  • 关闭自动透传:

    • 我们可以在组件内通过 inheritAttrs: false来关闭组件默认自动绑定行为