一、背景
在封装组件时候,经常要传递参数,调用事件。我们希望把主导权放在业务组件内,这是引入我们今天的主题: 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
引入后问题解决。
五、欢迎交流指正