开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第26天,点击查看活动详情
写在前面
第一次听说透传Attributes这个词,是在我阅读vue3官方文档的时候,之前每次看到这类名词的时候,多多少少能猜到大概是个什么意思,但是当我看到这个词的时候我是一脸懵,透传Attributes是个什么玩意儿。于是便有了这篇文章。
透传Attributes
“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props或 emits 的 attribute 或者
v-on事件监听器
通俗地理解就是父组件在调用子组件的时候,明明通过传值的操作给子组件传递属性,但是子组件却具有这个属性。比如常见的class, id, style。
class的透传
父组件给子组件传递一个class, 会绑定在子组件的容器元素上。如果一个子组件的根元素已经有了 class attribute,它会和从父组件上继承的值合并。
// 父组件
<HelloWorld class="hello-world" msg="Welcome to Your Vue.js App"/>
// 子组件
<template>
<div class="test-wrapper">
注入信息: {{location}}
<button @click="updateLocation" v-preReClick>点我点我</button>
</div>
</template>
最终渲染效果如下:
style的透传
style的效果和class一样,父组件给子组件传递一个style, 会绑定在子组件的容器元素上。如果一个子组件的根元素已经有了 style attribute,它会和从父组件上继承的值合并。
// 父组件
<HelloWorld style="fontSize: 16px" msg="Welcome to Your Vue.js App"/>
// 子组件
<template>
<div class="test-wrapper" style="color: blue">
注入信息: {{location}}
<button @click="updateLocation" v-preReClick>点我点我</button>
</div>
</template>
最终渲染效果如下:
v-on 监听器继承
click 监听器会被添加到 子组件的根元素,即那个原生的 <button> 元素之上。当原生的 <button> 被点击,会触发父组件的 onClick 方法。同样的,如果原生 button 元素自身也通过 v-on 绑定了一个事件监听器,则这个监听器和从父组件继承的监听器都会被触发。
// 父组件
<HelloWorld style="fontSize: 16px" msg="Welcome to Your Vue.js App" @click="parentClick"/>
// 子组件
<template>
<div class="test-wrapper" style="color: blue">
注入信息
<button @click="confrim">点我点我</button>
</div>
</template>
<script setup>
const confrim = () => {
console.log('触发了子组件的点击事件');
}
</script>
渲染效果如下:
深层组件的继承
有些情况下一个组件会在根节点上渲染另一个组件。此时这个组件接收的透传 attribute 会直接继续传给另一个组件。
禁用Attributes的继承
如果你不想要一个组件自动地继承 attribute,你可以在组件选项中设置 inheritAttrs: false。
<script>
// 使用普通的 <script> 来声明选项
export default {
inheritAttrs: false
}
</script>
如果在script标签中使用了setup,则需要这样写:
<script>
export default {
name: 'App',
inheritAttrs: false
}
</script>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
const parentClick = () => {
console.log('触发了父组件的点击事件');
}
在子组件中如果需要获取这个属性就是v-bind="$attrs"来获取对应的内容。
多根节点的 Attributes 继承
和单根节点组件有所不同,有着多个根节点的组件没有自动 attribute 透传行为。如果 $attrs 没有被显式绑定,将会抛出一个运行时警告。因此需要将$attrs显示绑定
<template>
<div class="test-wrapper" style="color: blue">
注入信息
<button @click="confrim" v-bind="$attrs.onClick">点我点我</button>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</div>
</template>
在 JavaScript 中访问透传 Attributes
在 <script setup> 中使用 useAttrs() API 来访问一个组件的所有透传 attribute:
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs();
const confrim = () => {
console.log('触发了子组件的点击事件');
}
</script>