序:
1、记住这个词啊,“透传”,意识就是穿透传播,从组件外面穿透进来到组件内部!
2、具体干啥的?我举个例子,你一个组件有一个props是style,正常我们是要在子组件的props去搞个接收这个参数定义它的default、type的,但是这个style在我们的script里是不做处理的,那你写个props就意义不大。这时候$attrs就解决了这个问题。
3、$attrs官网api地址===》组件实例 | Vue.js
4、博主微信公众号:“程序员野区”,关注公众号回复“加群”,可以进到博主微信群
正文:
一、简单demo
父组件
<template>
<list style="color:red"></list>
</template>
<script setup lang="ts">
import list from "./list.vue"
</script>
子组件
<template>
<ul>
<li>1</li>
<li>2</li>
</ul>
</template>
<script setup lang="ts">
</script>
我们可以看到运行后,style是自动加到了子组件ul标签上的,这个就叫做透传
注意,这是因为子组件只有一个根节点,你要是如下,有两个ul根节点节点,渲染的时候style是不会默认加到ul上的!!!!!!
二、禁用透传
子组件修改
<template>
<ul>
<li>1</li>
<li>2</li>
</ul>
</template>
<script setup lang="ts">
defineOptions({
inheritAttrs: false
})
</script>
可以看到父级的style是不会自动跑ul标签来了
三、只透传非props和emit绑定的
父组件
<template>
<list
style="color:red"
:id="1"
@callback="()=>{}"
@a="()=>{console.log(111)}"
></list>
</template>
<script setup lang="ts">
import list from "./list.vue"
</script>
子组件
<template>
<ul>
</ul>
</template>
<script setup lang="ts">
import { useAttrs } from 'vue'
defineOptions({
inheritAttrs: false
})
interface PropsType{
id?:number
}
const props=defineProps<PropsType>()
const emit=defineEmits(['callback'])
interface attrsType{
style?:string
onA?:()=>void
}
const attrs =<attrsType>useAttrs()
console.log(attrs)
console.log(attrs.style)//调用属性
attrs.onA(); //调用方法
debugger
</script>
因为callback、和id 都有被接收了,所以attr只接收onA和style这两个。
你可以用attrs.onA()去回调方法,就相当emit("a","");
也可以用attrs.style去获取属性
四、指定绑定
父组件
<template>
<list style="color:red" ></list>
</template>
<script setup lang="ts">
import list from "./list.vue"
</script>
子组件
<template>
<ul>
<li :style="($attrs as any).style"></li>
<!-- <li v-bind:style="($attrs as any).style"></li> -->
</ul>
</template>
<script setup lang="ts">
defineOptions({
inheritAttrs: false
})
</script>
inheritAttrs 设置成false,先把默认拼根节点的操作关掉,然后再拼接到li节点