一、背景
在封装组件时候,经常要传递参数,调用事件。我们希望把主导权放在业务组件内,这是引入我们今天的主题: 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>
三、参考文献:
v-bind="$props"、v-bind="$attrs"、v-on="listeners"_xueyue616的博客-CSDN博客
四、遇到小问题,顺手处理:
vue-cli项目解决方法:ElementUI校验[Violation] Added non-passive event listener to a scroll-blocking ‘touchmove‘ event. 问题解决_cabinx的博客-CSDN博客
nuxt项目解决方法:
安装插件:npm install -S default-passive-events
定义plugins:
nuxt.config.js引入plugins
引入后问题解决。
五、欢迎交流指正