vue3.0 透传属性和事件的使用方式
vue3.0 透传属性和事件
·
如何“透传属性和事件”
父组件在使用子组件的时候,如何“透传属性和事件”给子组件呢?
- 透传属性和事件并没有在子组件中用
props
和emits
声明 - 透传属性和事件最常见的如
@click
和class
、id
、style
- 当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上;如果根元素已有
class
或style
属性,它会自动合并
组合式API测试 :
父组件App.vue
<script setup>
import ChipVue from './components/Chip.vue';
function say() {
alert('Hello')
}
</script>
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在 props 声明 -->
<!-- 透传的事件(click)在子组件中并没有在 emits 声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
子组件 Chip.vue
<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>
渲染结果:
如何禁止“透传属性和事件”
- 当子组件只有一个根元素时,透传属性和事件会自动添加到该根元素上,那怎么阻止呢?
- 在选项式 API 中,你可以在组件选项中设置
inheritAttrs: false
来阻止; - 在组合式 API 的
<script setup>
中,你需要一个额外的<script>
块来书写inheritAttrs: false
选项声明来禁止
组合式API测试 :
父组件App.vue
<script setup>
import ChipVue from './components/Chip.vue';
function say() {
alert('Hello')
}
</script>
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在 props 声明 -->
<!-- 透传的事件(click)在子组件中并没有在 emits 声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
子组件 Chip.vue
<script>
export default {
inheritAttrs: false // 阻止自动透传给唯一的根组件
}
</script>
<!--
在组合式 API 的 <script setup> 中,
你需要一个额外的 <script> 块来书写 inheritAttrs: false 选项声明来禁止
-->
<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>
多根元素的“透传属性和事件”
多根节点的组件并没有自动“透传属性和事件”的行为,由于Vue
不确定要将“透传属性和事件”透传到哪里,所以我们需要v-bind="$attrs"
来显式绑定,否则将会抛出一个运行时警告。
组合式API测试:
父组件App.vue
<script setup>
import ChipVue from './components/Chip.vue';
function say() {
alert('Hello')
}
</script>
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在 props 声明 -->
<!-- 透传的事件(click)在子组件中并没有在 emits 声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
子组件Chip.vue
<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>
访问“透传属性和事件”
- 在选项式 API 中,我们可通过
this.$attrs
来访问“透传属性和事件” - 在组合式 API 中的
<script setup>
中引入useAttrs()
来访问一个组件的“透传属性和事件”
组合式API测试:
父组件App.vue
<script setup>
import ChipVue from './components/Chip.vue';
function say() {
alert('Hello')
}
</script>
<template>
<!-- 透传的属性(style,class,title)在子组件中并没有在 props 声明 -->
<!-- 透传的事件(click)在子组件中并没有在 emits 声明 -->
<ChipVue
class="rounded"
style="border: 1px solid blue;"
title="纸片"
@click="say"
/>
</template>
子组件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;
margin: 10px;
}
.rounded {
border-radius: 100px;
}
</style>
注意:
- 虽然这里的
attrs
对象总是反映为最新的“透传属性和事件”,但它并不是响应式的 (考虑到性能因素),你不能通过侦听器去监听它的变化- 如果你需要响应性,可以使用
prop
或者你也可以使用onUpdated()
使得在每次更新时结合最新的attrs
执行副作用
更多推荐
已为社区贡献1条内容
所有评论(0)