我本没有想着说要封装一个弹窗组件,但有同行的朋友在问我,而且弹窗组件也确实在项目开发中用的比较多。思前想后,又本着样式统一且修改起来方便的原则,还是再为大家分享一个我所封装的弹窗组件吧。

其实,并不是所有封装组件的方式都是一成不变的,你可以采用函数式组件这种能提高性能的方式,也可以使用带有状态和生命周期的普通组件的封装方式。但像dialog这种包含很多点击事件如确定或提交事件、取消或重置事件、右上角那个小叉叉的关闭事件等,又有可能包含嵌套其他组件如表格组件、表单组件、树形组件、穿梭框组件等的公共组件,其成分略微复杂,功能不太单一,你若要采用函数式组件的方式来封装也不是不可以,只是可能xue微要麻烦一些,我自己建议是不采用这种封装方式,就采用普通的封装方式就好。

至于普通组件的封装方式,我想大家平时在开发的过程中对所接触的普通组件即带有状态和生命周期,也能快乐地使用this关键词的组件已经是非常熟悉了,所以这种封装方式我就不会再做过多的介绍了。以下是具体的实现过程。

照例还是想来张效果图:



1、所封装的弹窗组件dialog.vue

<template>
<el-dialog
top="20vh"
class="el-dialog-cus"
v-bind="{...$attrs, ...{title, width, center}}"
:visible="visible"
:before-close="beClose"
append-to-body
>
<slot></slot>
<div slot="footer">
<el-button @click="cancel" plain>{{btnTxt[0]}}</el-button>
<el-button @click="confirm" type="primary" v-if="btnTxt[1]">{{btnTxt[1]}}</el-button>
</div>
</el-dialog>
</template> <script>
export default {
inheritAttrs: false,
props: {
title: {
type: String,
default: "提示",
},
width: {
type: String,
default: "420px",
},
center: {
type: Boolean,
default: true,
},
autoClose: {
type: Boolean,
default: true,
},
beforeClose: {
type: Function,
default: () => {}
},
btnTxt: {
type: Array,
default: () => ["取消", "确定"],
},
},
data() {
return {
visible: false,
};
},
methods: {
open(ok) {
this.ok = ok;
this.visible = true;
},
cancel() {
this.visible = false;
},
confirm() {
let cancel = () => this.cancel();
this.ok(cancel);
this.autoClose && cancel();
},
beClose(done) {
done();
this.beforeClose();
this.cancel();
},
},
};
</script> <style lang="scss">
.el-dialog-cus {
.el-dialog {
padding: 8px;
}
.el-dialog__title {
font-weight: bold;
}
.el-dialog__header {
padding: 20px 0 12px;
}
.el-dialog__headerbtn {
top: 8px;
right: 8px;
}
.el-dialog--center .el-dialog__body {
padding: 0 24px;
text-align: center;
}
.el-dialog__footer {
padding: 20px;
.el-button {
padding: 8px 20px;
& + .el-button {
margin-left: 40px;
}
}
}
}
</style>

对于以上的一些代码,我需要做一些特别的说明:

open(ok) {
this.ok = ok;
this.visible = true;
}

这段代码是弹出弹窗的方法,为的是在使用弹窗组件时,我们只需点击一个按钮并使用ref来获取弹窗组件的这个方法即可打开弹窗,剩下的关闭弹窗的操作就交给弹窗的确定或取消按钮来完成即可,我们不用再额外的写关闭弹窗的方法并将关闭弹窗的props参数传给弹窗组件。另外,在打开弹窗的方法中我还保存了一个ok事件,这个ok事件是用于在点击了弹窗组件的确定或提交按钮后所触发的回调方法,比如我们点击了弹窗的提交按钮,我们需要调一个接口来完成数据的存储或修改,那么这个ok事件就是为它实现的,毕竟弹窗组件充当的只是一个我们用于处理业务逻辑的中间桥梁。

confirm() {
let cancel = () => this.cancel();
this.ok(cancel);
this.autoClose && cancel();
}

这段代码是在点击弹窗的确定或提交按钮时触发的,但为什么要给一个之前保存的ok回调函数传一个关闭的方法参数呢,这是因为有时我们在点击了确定或提交的按钮后并不想立即关闭这个弹窗,而是想在几秒钟的倒计时后再关闭这个弹窗并跳转到其他页面,亦或是在A弹窗的基础上又弹出另外一个B弹窗,在B弹窗的基础上又弹出一个C弹窗。关闭C弹窗时,还能看到B弹窗,而不用在A弹窗的基础上通过点击事件再弹出B弹窗。这个时候就需要把关闭的方法当作参数传递给ok回调函数,让调用弹窗组件的人自行控制在什么时候关闭弹窗,这难道不香吗?只不过这个时候可能需要多给弹窗组件传一个参数autoClose来通知它是不是需要前端自行控制什么时候来关闭弹窗,毕竟弹窗组件在大多数情况下都是点击了确定或提交按钮后就直接被关闭了。

beClose(done) {
done();
this.beforeClose();
this.cancel();
}

这段代码是弹窗组件的关闭前before-close方法,element的官方解释是“关闭前的回调,会暂停Dialog的关闭”,官方还给了一个特别的说明:

before-close仅当用户通过点击关闭图标或遮罩关闭Dialog时起效。如果你在footer具名slot里添加了用于关闭Dialog的按钮,

那么可以在按钮的点击回调函数里加入before-close的相关逻辑。

它接收一个参数done,用于关闭Dialog。而this.beforeClose()是用来自定义关闭前的所要做的一些事情的方法。

还有一点需要注意的是:普通组件所有未声明的属性都会被解析到$attrs里面,并自动挂载到组件根元素上面。因为本次封装的弹窗组件的外面已经没有根元素了,也就是标签el-dialog的外面没有再包裹一层div标签,所以前边这就话的意义已经不大了,如果标签el-dialog的外面又包裹了一层div,那么“所有未声明的属性都会被解析到$attrs里面,并自动挂载到组件根元素上面”这句话就有意义了,也就是说这些未声明的属性也会出现在最外层的div上,如果不想让这些未声明的属性也会出现在最外层的div上,那么就可以用inheritAttrs:false来禁止。但本次封装的弹窗组件的外面没有根元素,所以加不加这个inheritAttrs:false都无所谓了。

2、弹窗组件的使用:

<template>
<div>
<el-button @click="open">点我打开</el-button>
<Dialog ref="dialog" :title="title" :width="width" :center="center" :btnTxt="btnTxt" :beforeClose="beforeClose" :content="'这里是中国'"><span>this is a dialog</span></Dialog>
</div>
</template> <script>
import Dialog from "@/components/dialog"; export default {
components: {
Dialog,
},
data() {
return {
width: '500px',
title: '温馨提示',
center: true,
btnTxt: ['取消', '提交'],
};
},
methods: {
open() {
this.$refs.dialog.open(cancel => {
// cancel();
console.log('点击提交按钮了')
});
},
beforeClose(){
console.log('关闭前');
},
}
};
</script>

以上具体的使用方法中:

open() {
this.$refs.dialog.open(cancel => {
// cancel();
console.log('点击提交按钮了')
});
}

这段代码就是用来打开或弹出弹窗组件,这里就是采用ref来获取弹窗组件的open方法,并向弹窗组件的open方法传一个回调函数,而这个回调函数的参数就是组件中ok事件触发时所返回的函数参数cancel,如果不要前端来自行控制弹窗的关闭,则不接收这个cancel参数即可。

封装Vue Element的dialog弹窗组件的更多相关文章

  1. 封装React AntD的dialog弹窗组件

    前一段时间分享了基于vue和element所封装的弹窗组件(封装Vue Element的dialog弹窗组件),今天就来分享一个基于react和antD所封装的弹窗组件,反正所使用的技术还是那个技术, ...

  2. vue+element table的弹窗组件

    在处理表格编辑相关的需求,是需要做一个弹框进行保存的:或者查看表格数据的详细信息时,也是需要做弹窗: 当然 ,这是类似于这样的 ,当然 element 已经帮我们做好 弹窗这一块 主要 我想记录的是 ...

  3. 封装Vue Element的table表格组件

    上周分享了几篇关于React组件封装方面的博文,这周就来分享几篇关于Vue组件封装方面的博文,也好让大家能更好地了解React和Vue在组件封装方面的区别. 在封装Vue组件时,我依旧会交叉使用函数式 ...

  4. 封装Vue Element的form表单组件

    前两天封装了一个基于vue和Element的table表格组件,阅读的人还是很多的,看来大家都是很认同组件化.高复用这种开发模式的,毕竟开发效率高,代码优雅,逼格高嘛.虽然这两天我的心情很糟糕,就像& ...

  5. 封装Vue Element的可编辑table表格组件

    前一段时间,有博友在我那篇封装Vue Element的table表格组件的博文下边留言说有没有那种"表格行内编辑"的封装组件,我当时说我没有封装过这样的组件,因为一直以来在实际开发 ...

  6. vue+element ui中select组件选择失效问题原因与解决方法

    codejing 2020-07-10 09:13:31  652  收藏 分类专栏: Web Vue Element UI 版权 .当表单form赋完值后,如果后续又对form中某一属性值进行操作如 ...

  7. Vue+element UI实现分页组件

    介绍 这是一个是基于element-UI的分页组件基础上,进行了二次封装的分页组件,在展示数据时,该分页组件采用了每显示一页数据,只请求当前页面的数据的请求策略,从而避免了一次性将数据全部请求所造成的 ...

  8. 封装Vue Element的upload上传组件

    本来昨天就想分享封装的这个upload组件,结果刚写了两句话,就被边上的同事给偷窥上了,于是在我全神贯注地写分享的时候他就神不知鬼不觉地突然移动到我身边,腆着脸问我在干啥呢.卧槽你妈,当场就把我吓了一 ...

  9. 【vue】vue +element 搭建项目,组件之间通信

    父子组件通信 父 通过props属性给 子传递数据 子 操作 父  this.$parent.XXX 子通过$emit传递参数 或者通过vue-bus vue-bus既可以实现父子组件之间的通信,也可 ...

随机推荐

  1. duoxiao OJ #910 【高手训练】【动态规划】梦中漫步 期望 LCA

    LINK:梦中漫步 当然也可以去一本通的Oj/loj上交(loj可能没有.. 期望好题.期望和dp往往是在一起的. 前置知识:1. 期望是线性可加的.2.和的期望等于期望的和. 从u出发每次随机选一条 ...

  2. 省选模拟赛day4

    怎么说?发现自己越来越菜了 到了不写题解写不出来题目的地步了.. 这次题目我都有认真思考 尽管思考的时候状态不太好 但是 我想 再多给我时间也思考不出来什么吧 所以写一份题解. T1 n个点的有根树 ...

  3. 笨办法学python3练习代码ex21.py

    def add(a, b): print(f"ADDING {a} + {b}") return (a + b) def subtract(a, b): #subtract :减去 ...

  4. 100% 展示 MySQL 语句执行的神器-Optimizer Trace

    在上一篇文章<用Explain 命令分析 MySQL 的 SQL 执行>中,我们讲解了 Explain 命令的详细使用.但是它只能展示 SQL 语句的执行计划,无法展示为什么一些其他的执行 ...

  5. 用MPI进行分布式内存编程(1)

    <并行程序设计导论>第三章部分程序 程序3.1运行实例 #include<stdio.h> #include<string.h> #include<mpi.h ...

  6. 005_go语言中的for循环

    代码演示 package main import "fmt" func main() { i := 1 for i <= 3 { fmt.Println(i) i = i + ...

  7. 导航菜单(动画)--- jQuery

    本文章实现是一个导航菜单的功能 (1)点击当前菜单显示二级菜单,再次点击收起当前菜单. (2)当有一个二级菜单显示,点击其他菜单,上一个已点击菜单会收起.只展示当前点击的菜单,只显示一个菜单,类似手风 ...

  8. DB2 创建存储过程保存:XX 后面找到异常标记 "END-OF-STATEMENT"。

    存储过程最后一行加结束符@: 然后执行:db2 -td@ -vf /home/WGJ/proc_data_calculate.sql [slsadmin@localhost /]$ db2 -td@ ...

  9. java Iterator迭代器

    一 Iterator迭代器概述 java中提供了很多个集合,它们在存储元素时,采用的存储方式不同.我们要取出这些集合 中的元素,可通过一种通用的获取方式来完成. Collection集合元素的通用获取 ...

  10. Qt之先用了再说系列-多线程方式2

    继Qt之先用了再说系列-多线程方式2 本次说说在Qt里多线程使用第2种方式,也是qt官方比较推荐用的方式,相对与直接继承QThread 重写run方法中灵活了一些,如果第一次使用可能会转不湾来,没有直 ...