vue el-message封装
我亚索贼六丶 人气:1前言
最近对项目进行改造,发现在el-message使用中,如果遇到服务器挂了或者在重启等其他情况,页面message会弹出一大堆报错信息,看起来很不美观,所以对el-message进行重写改造,这里记录下改造中遇到的问题和实现,希望能对你有点帮助。
实现方法
实现方法有很多种,可以根据你实际项目情况决定使用哪一种。
方法一
直接css里面给这个样式,简单省事,但是这样子有一个问题所有的message都重叠在一起,浅入浅出的动画效果不好,不是很推荐。
.el-message { top: 20px !important; }
方法二
直接使用el-message的closeAll方法,弹消息之前关闭所有的消息,也很简单,但是这样会有一个明显的抖动,所以也不是很推荐(不介意的话也可以这样写)。
this.$message.closeAll(); this.$message.error("错误提示3");
方法三(有残缺的方法,可以带着问题看方法4)
对message进行改造,重写message方法,新建一个message.js,定义一个class类,给这个class赋予success,error,info,warning4个方法,根据el-message的使用方法,分为:this.$message.success('测试成功消息') 和this.$message({type:'success',message:'测试成功消息'})这两种情况,所以要根据传入的值是字符串还是对象做一下判断。
import { Message } from "element-ui"; class ZMessage { constructor() { ["success", "error", "info", "warning"].forEach((type) => { this[type] = function (options) { if (isObject(options)) { const { type='info', ...rest } = options; Message({ type, ...rest, }); return; } Message({ type: type, message: options, }); }; }); } } //判断传入的是否是Object function isObject(content) { return ( Object.prototype.toString.call(content) === "[object Object]" && !!content.message ); } export default new ZMessage;
然后在main.js里面引入,覆盖掉el-message的方法
import ZMessage from "@/utils/message"; Vue.prototype.$message = ZMessage;
这样message重写第一步就完成了,第二步需要判断当前message的数量,如果小于1,就弹消息,仔细观察message,我们可以通过document.getElementsByClassName("el-message").length来获取当前弹框的数量,如果大于等于1就不再弹框,如果小于1就弹框。
class ZMessage { constructor() { ["success", "error", "info", "warning"].forEach((type) => { this[type] = function (options) { //这里加一个判断 if (document.getElementsByClassName("el-message").length === 0) { if (isConfig(options)) { const { type = "info", ...rest } = options; Message({ type, ...rest, }); return; } Message({ type: type, message: options, }); } }; }); } }
这样弹消息即使多次触发,也只会弹一个消息出来,正当我以为已经完事了,却发现还有新的问题:
- 问题1:this.$message({type:'error',message:'测试消息'}) 报错了
- 问题2:弹的消息不会更新,必须要等上一条消息消失后,才会出现新的
方法四
对于方法三存在的两个问题,所以我们需要对方法三进行改造,还是那个文件message.js,这里不用class了,因为对外export的方法是new ZMessage(),message的值无法直接传递过来,暂时还没有想好咋传过来,所以就不用class了,所以对ZMessage进行下改造
const ZMessage = function (options) { if (isObject(options)) { const { type = "info", ...rest } = options; showMessage({ type, ...rest, }) return; } showMessage({ type: options.type || "info", message: options, }) }; ["success", "error", "info", "warning"].forEach((type) => { ZMessage[type] = function (options) { if (isObject(options)) { ZMessage({ type: type, ...options, }); return; } ZMessage({ type, message: options, }); }; }); function isObject(content) { return ( Object.prototype.toString.call(content) === "[object Object]" && !!content.message ); } function showMessage(options) { Message({ ...options }); } export default ZMessage;
这样第一个问题,this.$message({type:'error',message:'测试消息'})就不会报错了,接下来解决第二个问题,值不会更新的问题,可以定义一个msgInstance变量,如果有新的值来了,就关闭上一个消息
var msgInstance = null; const ZMessage = function (options) { if (msgInstance) { //更新弹框 msgInstance.close(); } if (isObject(options)) { const { type = "info", ...rest } = options; showMessage({ type, ...rest, }) return; } showMessage({ type: options.type || "info", message: options, }) }; ["success", "error", "info", "warning"].forEach((type) => { ZMessage[type] = function (options) { if (isObject(options)) { ZMessage({ type: type, ...options, }); return; } ZMessage({ type, message: options, }); }; }); function isObject(content) { return ( Object.prototype.toString.call(content) === "[object Object]" && !!content.message ); } function showMessage(options) { msgInstance=Message({ ...options }); } export default ZMessage;
这样就完美解决了上面出现的两个问题,到这里目标基本已经实现;但是,又想到如果要求不止出现一个message,我要只出现两个甚至多个怎么办,所以在方法四的基础上,改造出来方法五,参考ant-design-vue,对最大数量可调配。
方法五
定义一个maxCount参数,需要message全局定义,在调用message方法之前,先定下message的最大数量,每次点击弹框的时候都往messageList里面插入一个当前的message实例,close的时候将这条数据删除,再给message新加一个config方法,maxCount就传给config方法,在这个里面配置。
import { Message } from "element-ui"; // 定义message的当前数量 var messageList = []; // 定义初始最大数量 var messageMaxCount = 0; const ZMessage = function (options) { if (messageMaxCount && messageList.length >= messageMaxCount) { //更新弹框 messageList[0].close(); } if (isObject(options)) { const { type = "info", ...rest } = options; messageList.push( showMessage({ type, ...rest, }) ); return; } messageList.push( showMessage({ type: options.type || "info", message: options, }) ); }; ["success", "error", "info", "warning"].forEach((type) => { ZMessage[type] = function (options) { if (isObject(options)) { ZMessage({ type: type, ...options, }); return; } ZMessage({ type, message: options, }); }; }); ZMessage.config = function (options) { const { maxCount } = options; if (maxCount) { if (typeof maxCount !== "number") { return console.error("参数类型错误:maxCount应为number类型"); } messageMaxCount = maxCount; } }; function isObject(content) { return ( Object.prototype.toString.call(content) === "[object Object]" && !!content.message ); } function showMessage(options) { const { onClose:close, ...rest } = options; return Message({ ...rest, //关闭时,除了传入的close方法,还需要将对应的实例删除 onClose: (val) => { if(close){ close() } messageList = messageList.filter((item) => item.id != val.id); }, }); } export default ZMessage;
使用:
this.$message.config({ maxCount:3 })
最后
到这里,el-message就已经改造完毕,你可以根据自己的实际情况使用上面的任意方法,希望这个文章能对你有所帮助,还有其他的办法可以评论留言下,大家一起学习进步。
加载全部内容