前言
Vue3推出了一系列新功能和改进。使用下来后,其中一个很实用的新特性就是透传 Attributes(透传属性)。本文将介绍 Vue3中的透传 Attributes,并提结合代码示例来展示它在实际项目中的使用。
一、什么是透传 Attributes?
在 Vue 中,父组件可以通过属性(Props)向子组件传递数据,以控制子组件的行为和外观。然而,在某些情况下,我们希望将父组件的属性直接传递给子组件内部的 HTML 标签或自定义组件。
以前,我们需要手动将这些属性逐层传递下去,但现在 Vue 3 引入了透传 Attributes 来简化这个过程。
透传 Attributes 允许在组件中自动将父组件的未声明 Props 直接传递给子组件的根元素或另一个指定元素。这意味着你可以更方便地在子组件中访问到父组件的属性,而无需手动一层层传递。
Vue3中文官网解释
二、如何使用透传 Attributes?
1. 具体使用
- 父组件:直接传属性
<template>
<div>
<ChildComponent name="John Doe" age="25" />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue';
</script>
- 子组件:使用 $attrs 或 useAttrs() 接收属性
<template>
<div>
<h2>{{ name }}</h2>
<p>{{ $attrs.age }}</p>
<!-- 在模板的表达式中直接用 $attrs 访问到 -->
<p>{{ attrs.age }}</p>
</div>
</template>
<script setup>
// 在js里 使用 useAttrs() API 来访问到
import { useAttrs } from 'vue'
defineProps({
name: String
})
const attrs = useAttrs()
console.log(attrs)
</script>
打印:
在上述示例中,我们有一个父组件,在模板中引入了一个子组件 <ChildComponent>
。父组件给子组件传递了两个属性:name
和 age
。
在子组件中,我们使用了 props
对象来声明 name
属性,而没有声明 age
属性。这时,age
属性就会被视为透传 Attributes,打印的内容中和渲染的p标签里,包含了父组件传递的未声明 Props age
的值。
通过透传 Attributes,我们可以轻松地在子组件中访问到父组件的属性,而不需要手动声明和传递。
2. 注意事项
当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。多个根节点的组件没有自动 attribute 透传行为。如果
$attrs
没有被显式绑定,或者没有被使用,将会抛出一个运行时警告。
把上面的子组件改一下,多一个div根节点:
<template>
<div>
<h2>{{ name }}</h2>
</div>
// 多了一个根元素
<div></div>
</template>
<script setup>
defineProps({
name: String
})
</script>
此时报错表示:vueVue 不知道要将 attribute 透传到哪里。
解决办法:如果 $attrs 被显式绑定 或者 使用,或者 两者同时出现,则不会有警告。
<template>
<!-- 显示绑定 -->
<div v-bind="$attrs">
<h2>{{ name }}</h2>
</div>
<div>
<!-- 使用 -->
<p>{{ $attrs.age }}</p>
</div>
</template>
<script setup>
defineProps({
name: String
})
</script>
可能这里会有人疑惑,既然显示绑定了上面的div,下面的div依旧可以通过 $attrs 使用属性,那显示绑定的作用是什么?不是多此一举了吗?
其实不然。让我们把父组件改一下,添加一个id属性,子组件不做更改:
<template>
<div>
<ChildComponent id="custom-layout" name="John Doe" :age="25" />
</div>
</template>
<script setup>
import ChildComponent from './ChildComponent.vue'
</script>
这时就可以看到,父组件传递下来的id属性,自动添加到了使用 v-bind 显示绑定的元素上了。
三、透传 Attributes 的实际应用
1. 外部库集成
当我们在使用外部库或第三方组件时,可能需要将一些属性传递给这些组件以进行配置或自定义。透传 Attributes 可以很方便地将父组件的属性直接传递给外部库或第三方组件。
<template>
<div>
<ThirdPartyComponent v-bind="$attrs" />
</div>
</template>
<script setup>
import ThirdPartyComponent from 'third-party-library';
</script>
在上述示例中,我们通过 $attrs 函数来获取父组件的所有未声明 Props,并将其直接传递给一个名为 ThirdPartyComponent 的第三方组件。
2. 高阶组件
透传 Attributes 还可以用于高阶组件(Higher-Order Components)的开发。高阶组件是一个接收一些额外属性,并将这些属性传递给内部子组件的组件。
<template>
<div>
<WrappedComponent v-bind="$attrs" />
</div>
</template>
<script setup>
import WrappedComponent from './WrappedComponent.vue';
</script>
在上述示例中,我们创建了一个高阶组件,并通过 attrs
函数来获取父组件的所有未声明 Props,并将其直接传递给子组件 WrappedComponent
。
3. 动态组件
使用动态组件时,透传 Attributes 可以让父组件的属性传递到被动态渲染的组件中。
<template>
<div>
<component :is="dynamicComponent" v-bind="$attrs" />
</div>
</template>
<script setup>
const dynamicComponent = 'ChildComponent';
</script>
在上述示例中,我们使用了动态组件来根据条件渲染不同的组件。通过 :is
和 v-bind
,我们可以将父组件的所有未声明 Props 透传给被动态渲染的组件。