一、背景
在封装组件时候,经常要传递参数,调用事件。我们希望把主导权放在业务组件内,这是引入我们今天的主题: `v-bind="$attrs"` `v-on="$listeners"`
使用 `v-bind="$attrs" `属性,`vm.$attrs `是一个属性,其包含了**父作用域中不作为 prop 被识别 (且获取) 的特性绑定 (class 和 style 除外)**。这些**未识别的属性**可以通过` v-bind="$attrs" `传入内部组件。**未识别的事件**可通过`v-on="$listeners"`传入。
父组件
// 业务代码
<template>
<div class="container">
<div>
<el-button @click="showDialog" type="primary" style="margin:50px;">show-dialog</el-button>
<test-dialog
top="8vh"
width="85%"
:title="'dialog-title'"
:visible.sync="dialogVisible"
:footer-visible="true"
@refuse="handleClose"
@confirm="handleConfirm"
@closeBtn="handleClose"
>
<template #content>
<div>
content
</div>
</template>
</test-dialog>
</div>
</div>
</template>
<script>
import TestDialog from "./components/dialog.vue";
export default {
components: {
TestDialog
},
data() {
return {
dialogVisible: false,
};
},
methods: {
showDialog(){
console.log('hide')
this.dialogVisible = true
},
handleClose() {
console.log('close')
this.dialogVisible = false;
},
handleConfirm() {
console.log('success')
},
}
};
</script>
子组件
// 组件代码
<template>
<div>
<el-dialog
v-bind="$attrs"
ref="mDialog"
:visible="$attrs.visible || instanceVisible"
:width="'500px'"
:show-close="false"
v-on="$listeners"
>
<div slot="title" class="dialog--title">
<span>{{ $attrs.title || "提示" }}</span>
<span class="dialog--title__close" @click="close">
<i class="el-icon-close"></i>
</span>
</div>
<div class="content">
<slot name="content" />
</div>
<div slot="footer">
<div>
<el-button refuse="true" plain @click="refuse">{{
$attrs["refuse-text"] || "取消"
}}</el-button>
<el-button type="primary" @click="confirm">{{
$attrs["confirm-text"] || "确定"
}}</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
import { throttle } from "lodash";
export default {
name: "Dialog",
inheritAttrs: false,
data() {
return {
instanceVisible: false,
}
},
methods: {
close() {
this.$listeners.closeBtn();
},
refuse: throttle(
function func() {
this.$listeners.refuse();
},
1500
),
confirm: throttle(
function func() {
this.$listeners.confirm();
},
1500
)
}
}
</script>
<style lang="less">
.dialog--title {
font-size: 18px;
line-height: 24px;
padding: 12px 14px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e5e5e5;
margin-bottom: 20px;
.dialog--title__close:hover {
cursor: pointer;
}
}
</style>