一、如何透传属性和事件
透传是一个通讯层面的概念,指的是在通讯中不管传输的业务内容如何,只负责将传输的内容由源地址传输到目的地址,而不对业务数据内容做任何改变。
在vue上来讲,我们的组件存在深层嵌套的场景,例如:A -> B -> C
父组件在使用子组件的时候,如何“透传属性和事件”给子组件呢?
1、透传属性和事件并没有在子组件中用props和emits声明
2、透传属性和事件最常见的如@click和class、id、style
3、当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上;如果根元素已有class或style属性,它会自动合并
实例:
子组件Chip.vue
<script setup>
</script>
<template>
<!-- 当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上
如果根元素已有class或style属性,它会自动合并 -->
<button class="chip" style="box-shadow: 0 0 8px grey;">
普通纸片
</button>
</template>
<style>
.chip {
border: none;
background-color: rgb(231,231,231);
padding: 8px 15px;
}
.rounded {
border-radius: 100px;
}
</style>
父组件App.vue
<script setup>
import ChipVue from './components/Chip.vue'
function say() {
alert('Hello')
}
</script>
<!-- 视图区域(view) -->
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
<!-- 透传的事件(click)在子组件中并没有在emits声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
渲染结果:
<button class="chip rounded" title="纸片" style="box-shadow: grey 0px 0px 8px; border: 1px solid blue;"> 普通纸片 </button>
二、如何禁止透传属性和事件
当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上,那怎么阻止呢?
1、在选项式 API 中,你可以在组件选项中设置inheritAttrs: false来阻止;
2、在组合式 API 的"<script setup>"中,你需要一个额外的"<script>"块来书写inheritAttrs: false选项声明来禁止;从 3.3 开始你也可以直接在"<script setup>"中使用 defineOptions
实例:
Chip.vue
<script setup>
defineOptions({
inheritAttrs: false //阻止自动透传给唯一的根组件
})
</script>
<template>
<!-- 当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上
如果根元素已有class或style属性,它会自动合并 -->
<button class="chip" style="box-shadow: 0 0 8px grey;">
普通纸片
</button>
</template>
<style>
.chip {
border: none;
background-color: rgb(231,231,231);
padding: 8px 15px;
}
.rounded {
border-radius: 100px;
}
</style>
App.vue
<script setup>
import ChipVue from './components/Chip.vue'
function say() {
alert('Hello')
}
</script>
<!-- 视图区域(view) -->
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
<!-- 透传的事件(click)在子组件中并没有在emits声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
三、多根元素的“透传属性和事件”
多根节点的组件并没有自动“透传属性和事件”的行为,由于Vue不确定要将“透传属性和事件”透传到哪里,所以我们需要v-bind="$attrs"来显式绑定,否则将会抛出一个运行时警告。
实例:
Chip.vue
<script setup>
</script>
<template>
<!-- 多根节点的组件并没有自动“透传属性和事件”的行为 -->
<button class="chip">
普通纸片
</button>
<hr>
<button class="chip" v-bind="$attrs">
普通纸片
</button>
<hr>
<button class="chip" v-bind="$attrs">
普通纸片
</button>
</template>
<style>
.chip {
border: none;
background-color: rgb(231,231,231);
padding: 8px 15px;
}
.rounded {
border-radius: 100px;
}
</style>
App.vue
<script setup>
import ChipVue from './components/Chip.vue'
function say() {
alert('Hello')
}
</script>
<!-- 视图区域(view) -->
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
<!-- 透传的事件(click)在子组件中并没有在emits声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
四、访问“透传属性和事件”
1、在选项式 API 中,我们可通过this.$attrs来访问“透传属性和事件”
2、在组合式 API 中的"<script setup>"中引入useAttrs()来访问一个组件的“透传属性和事件”
实例:
Chip.vue
<script setup>
import { useAttrs } from 'vue'
//获得透传的属性和事件对象
let attrs = useAttrs()
//在JS中访问透传的属性和事件
function showAttrs() {
console.log(attrs)
console.log(attrs.class)
console.log(attrs.title)
console.log(attrs.style)
attrs.onClick()
}
</script>
<template>
<button class="chip" v-bind="attrs">
普通纸片
</button>
<hr>
<h6>{{ attrs }}</h6>
<ul>
<li>{{ attrs.title }}</li>
<li>{{ attrs.class }}</li>
<li>{{ attrs.style }}</li>
</ul>
<button @click="attrs.onClick()">执行透传的事件</button>
<hr>
<button @click="showAttrs">在JS中访问透传的属性和事件</button>
</template>
<style>
.chip {
border: none;
background-color: rgb(231,231,231);
padding: 8px 15px;
}
.rounded {
border-radius: 100px;
}
</style>
App.vue
<script setup>
import ChipVue from './components/Chip.vue'
function say() {
alert('Hello')
}
</script>
<!-- 视图区域(view) -->
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在props声明 -->
<!-- 透传的事件(click)在子组件中并没有在emits声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
1031

被折叠的 条评论
为什么被折叠?



