简单来说:
$attrs
与$listeners
是两个「对象」,$attrs
里存放的是父组件中绑定的非 Props 属性,$listeners
里存放的是父组件中绑定的非原生事件。
//子组件
//$attrs 可以收集父组件中的所有传过来的属性 除了那些在组件中没有通过 props 定义的。
//唯一缺点 没在props定义的属性 会显示在生成的html标签上
//解决办法:通过inheritAttrs:false,避免顶层容器继承属性
<template>
<el-dialog
:title="title"
:visible="dialogVisible"
@close="$emit('update:dialogVisible', false)"
:width="width"
:close-on-click-modal="modal"
v-bind="$attrs" /**关键代码**
>
<slot name="dialog-body"></slot>
<div slot="footer" class="dialog-footer">
<slot name="modal-footer">
<el-button @click="$emit('update:dialogVisible', false)">取 消</el-button>
<el-button type="primary" @click="$emit('confirm')" size="small">确 定</el-button>
</slot>
</div>
</el-dialog>
</template>
<script>
export default {
name: "my-dialog",
inheritAttrs:false #关键代码
props: {
dialogVisible: Boolean,
title: String,
width: {
type: String,
default: "500px"
},
modal: {
type: Boolean,
default: false
}
}
};
</script>
//父组件 里使用
//:fullscreen="true" 并没在子组件props内定义 依然传入了子组件
//让dialog 全屏
<my-dialog :fullscreen="true" :dialogVisible.sync="flag" @confirm="close" title="测试弹框"></my-dialog>
其他例子
//componentA
<template>
<div class="component-a">
<component-b :name="name" :tag="tag" :age="age" @click.native="say" @mouseover="sing"></component-b>
</div>
</template>
<script>
import componentB from "./ComponentB";
export default {
name: "componentA",
components: { componentB },
data() {
return {
name: "六哥",
tag: "帅",
age: 18
};
},
methods: {
say() {},
sing() {}
}
};
</script>
//componentB
<template>
<div class="component-b" v-on="$listeners" v-bind="$attrs"></div>
</template>
<script>
export default {
name: "ComponentB",
props: {
age: Number
},
mounted() {
console.log(this.$attrs, this.$listeners);
//{name: "六哥", tag: "帅"}, {mouseover: ƒ}
}
};
</script>