我们做一些重要操作的时候,往往需要弹窗一个提示框,告诉用户这是一个需要小心的操作,是否继续,用户点击确定后才会开始执行,这种操作写起来比较繁琐,如下所示,要写一堆代码,今天我来讲解下组件的高级封装技巧,让你一行代码搞定有弹出框的点击操作
透传 Attributes
想要自己封装组件,props和attributes的知识是必不可少的,详细的可以自己看文档
props文档: https://cn.vuejs.org/guide/components/props.html
attributes文档: https://cn.vuejs.org/guide/components/attrs.html
简单来说,组件有个$props属性,里面接收了所有你在组件props里面定义的属性,网上很多资料说$props是不包含方法的,其实这种说法是错误的,当你在emits里面申明了方法时,这些方法也会包含在$props里面,而$attrs里面则包含了所有不在props和emits里面申明的属性和方法,这种特性很有用,可以让我们很方便的对组件进行封装和扩展
属性的绑定
v-bind="$attrs"这种写法可以绑定所有未在props里面定义的属性,比如我定义了一个组件叫ui-button,代码如下,那我这个ui-button表现就和el-button一样,所有el-button内置的属性都适用于ui-button
<el-button v-bind="$attrs">
</el-button>
属性的合并与覆盖
对于有些属性,vue会进行合并,如class和style,对于大部分属性,后面的会覆盖前面的,比如使用<el-button v-bind="$attrs" type="primary"/>即使$attrs里面有type,后面的type也会覆盖$attrs里面的type
需要特别注意的是方法不会覆盖,而是会合并,也就是说<el-button v-bind="$attrs" @click="click"/>这总写法,如果$attrs里面有click监听,那会和后面的click方法一起执行
ui-button的封装
我们定义一个组件叫ui-button,封装了element plus的el-button,这个ui-button只扩展了一个属性叫confirmText,如果confirmText为空,则表现跟el-button一模一样,直接触发点击事件,如果confirmText不为空,则弹框确定,只有点击确定才会触发click,这里需要注意的是我们在emits里面申明了click方法,这样click方法不会出现在$attrs里面,就不会和后面的@click冲突了
<template>
<el-button v-bind="$attrs" @click="click($event)">
<slot></slot>
</el-button>
</template>
<script>
import {ElMessageBox} from "element-plus";
export default {
name: "ui-button",
inheritAttrs: false,
emits: ['click'], // 申明对外触发的事件
props: {
confirmText: { type: String }, // 提示文本,如果不为空则会弹出提示信息
},
methods: {
click(e) {
if (this.confirmText) {
ElMessageBox.confirm(
this.confirmText,
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
},
).then(() => {
this.$emit('click', e)
}).catch(() => {
})
} else {
this.$emit('click', e)
}
},
}
}
</script>
<style scoped>
</style>
ui-button的使用
使用起来跟el-button一模一样,只是比el-button多了个confirmText属性,设置了该属性就会弹框确认,使用起来超级方便
<template>
<div>
<ui-button type="danger" @click="onDelete(1)" confirmText="是否删除该条记录?">删除</ui-button>
</div>
</template>
<script setup>
import UiButton from "@/components/ui-button.vue";
function onDelete(id) {
console.log('执行删除,id: ' + id)
}
</script>