$attrs
当父组件给子组件传值,子组件并没有接收数据时,此时数据在$attrs中可以拿到,并且如果子组件不需要使用数据,而孙组件需要,则可以直接v-bind="$attrs"传给孙。
<-- 父组件 -->
<div>
<myButton type="primary"/>
<div>
<-- 子组件 -->
<el-button v-band='$attrs'>主要按钮</el-button>
这样的写法就会直接将type="primary"传递给孙组件中,子组件不需要使用props来接收,这样写的好处是无需再子组件中定义props,属性有时候也并不确定
同样孙组件中也可以采用props来接受根组件传递过来的参数
<template>
<button></button>
</template>
<script>
export default {
inheritAttrs: false,
props: [
"type",//注意props里的参数名称不能改变,必须和根组件传递过来的是一样的
],
mounted(){
console.log(this.$attrs) //可直接使用数据或者调用根组件的方法
}
};
</script>
子组件有多个根节点时
如果子组件存在多个根节点时,需要手动绑定具体的根节点,否则就会抛出警告
这样就能解决
<template>
<div :style="$attrs['style']">我是孙组件第一个div</div>
<div>我是孙组件的第二个div</div>
</template>
<script>
inheritAttrs
inheritAttrs的值为boolean,默认为true,由于v-band='$attrs'传递过来的值会作为dom元素上的属性存在,设置为false可以阻止这个行为,这些属性仍然可以通过$attrs来访问,(vue2中class和style不会受到影响,但是vue3中class和style会受影响)
vue2中
vue3中
vue3禁止inheritAttrs
如果你使用了 <script setup>,你需要一个额外的 <script> 块来书写这个选项声明:
<script>
// 使用普通的 <script> 来声明选项
export default {
inheritAttrs: false
}
</script>
<script setup>
// ...setup 部分逻辑
</script>
vue3中访问$attrs
<script setup>
import { useAttrs } from 'vue'
const attrs = useAttrs()
</script>
如果没有使用setup语法糖,则
export default {
setup(props, context) {
// 透传 attribute 被暴露为 ctx.attrs
console.log(context.attrs)
}
}
$slots
普通插槽
$slots可以拿到父组件所传递过来的所有插槽,它是一个对象,key 名对应着插槽名。
<!-- 子组件 -->
<template>
<el-button v-bind="$attrs">
<!-- 通过遍历实现插槽透传 -->
<template v-for="(item, key, index) in $slots" :key="index" v-slot:[key]>
<slot :name="key"></slot>
</template>
</el-button>
</template>
<!-- 父组件 -->
<template>
<MyButton type="primary">
<template #default>按钮</template>
<template #icon>111</template>
<template #footer>ceshi</template>
</MyButton>
</template>
作用域插槽
如果插槽是一个作用域插槽,传递给该插槽函数的参数可以作为插槽的 prop 提供给插槽。
<!-- 子组件 -->
<template>
<el-button v-bind="$attrs">
<!-- 通过便利实现插槽透传 -->
<!-- v-slot:[key] 绑定到对应的插槽中 -->
<template v-for="(item, key, index) in $slots" :key="index" v-slot:[key]>
<slot :name="key" v-if="key === 'icon'" :count="99"></slot>
<slot :name="key" v-else></slot>
</template>
</el-button>
</template>
<!-- 父组件 -->
<template>
<MyButton type="primary">
<template #default>按钮</template>
<template #icon="iconProps">11{{ iconProps.count }}</template>
<template #footer>ceshi</template>
</MyButton>
</template>