透传属性
在Vue3中有一个很有意思的特性,透传属性。透传又分为自动透传绑定,和手动绑定两种。
什么是透传属性? 透传属性指组件在使用的时候,作用在组件上的属性,会被向下流动,绑定到组件内的标签中。
什么属性可以透传?
class,id,style,属性,事件等头可以透传到组件内的标签中。(前提是属性和事件没有在组件中定义,后面会介绍)
一起养成写作习惯!这是我参与「掘金日新计划 · 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
传入一个属性或者是事件,如果这个属性、事件没有在组件中定义,那么它依然是透传属性,因为没有东西接受它。
如果是事先定义了
defineEmits或defineProps来接受它,那么它就是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来关闭组件默认自动绑定行为。
- 我们可以在组件内通过