透传
1 什么是透传
将没有被组件声明为 props 或 emits 的 attribute 或者 v-on
事件监听器传递给组件。
下面用个例子说明透传具体“长啥样”:
src/components/test.vue
<template>
<div>hello</div>
</template>
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
console.log(attrs)
</script>
src/views/table/index.vue
<template>
<test v-model:age="age" name="Jack" girl-friend="Marry" @row-click="fn" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import Test from '#/components/test.vue'
const age = ref(20)
function fn() {
console.log('row click')
}
</script>
- 和 props 有所不同,透传 attributes 在 JavaScript 中保留了它们原始的大小写
- 像
@row-click
这样的一个v-on
事件监听器将在此对象下被暴露为一个函数onRowClick
2 自动透传
如果组件是单根节点,没有被组件声明为 props 或 emits 的 attribute 或者 v-on
事件监听器会自动传递到组件的根元素/组件上。
如何禁止自动透传?
设置 inheriAttrs: false
,会禁止上述行为。
3 手动透传
多根节点组件不会自动透传;单根节点组件,如果设置了 inheriAttrs: false
,也不会自动透传。对于这两种情况,如果想要使用没有被组件声明为 props 或 emits 的 attribute 或者 v-on
事件监听器,就需要“手动透传”
4 如何访问没有被组件声明为 props 或 emits 的 attribute或者 v-on
事件监听器
4.1 模板中
$attrs
4.2 JavaScript 中
选项式 API
this.$attrs
组合式 API
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
不管 inheriAttrs
为 false 还是 true,不影响上面的访问方式,inheriAttrs
只是用来控制单根节点组件是否可以自动透传。
5 注意
在非单根节点组件中使用没有被组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器,需要设置 inheritAttrs 为 false,否则控制台报警告,如:
Extraneous non-props attributes (visible) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.
不能直接 watch attrs,否则提示 A watch source can only be a getter/effect function, a ref, a reactive object, or an array of these types.
const attrs = useAttrs()
watch(attrs, () => {
})
应该这样写:
const attrs = useAttrs()
watch(() => attrs, () => {
})