前言
这篇文章主要是纪录一下使用单例模式封装element-ui中message的场景,以及是怎么做的。希望能为大家以后解决问题提供一个思路。
单例模式封装message
先贴代码,需要自取。
messageInstan.vue
js
import { Message } from "element-ui";
let messageInstance = null;
function DoneMessage(options) {
//如果弹窗已存在先关闭
if (messageInstance) {
messageInstance.close();
}
messageInstance = Message(options);
}
let mainMessage = throttle(DoneMessage, 500);
let arr = ['success', 'warning', 'info', 'error'];
arr.forEach(function (type) {
mainMessage[type] = function (options) {
if (typeof options === 'string') {
options = {
message: options
};
}
options.type = type;
return mainMessage(options);
};
});
export default mainMessage;
function throttle(fn, delay) {
let timer = null
return function (...args) {
if (timer) {
return
}
fn.apply(this, args)
timer = setTimeout(() => {
timer = null
}, delay)
}
}
使用
js
import messageInstance from './components/messageInstance'
messageInstance.warning("请先保存当前编辑项");
应用场景
我的使用场景是在一个可拖拽排序的列表中
原来开发这块的人,引入的第三方库是sortablejs。在该库提供的onEnd回调函数中,也就是拖拽松开的那一刻调用接口,保存交换后的数据,然后重新请求列表。这段代码是两年前写的,今天突然提出来了一个bug,就是说点编辑的时候出现输入框,这时候拖动会导致后端接口报错。
原因是在调用接口的时候把未保存的空文本也传给后端了,下图是后端大佬排查发现的问题,以及给出的修改方案。
大佬让列表有未保存的值时,不允许拖拽并且给出提示。这个修改意见给的很到位,改起来也很简单,不就是在发送请求前判断下列表有没有未保存的字段嘛,有了就在函数内直接return,不发请求了不就完事了。就这么改!
上图为改完后的样子,有未保存项时,接口确实没调用并给出了提示,但它却交换了位置。这是为啥啊,原来是第三方库搞得鬼,它直接完成了拖拽逻辑。我就算return了,发送接口的代码没执行。但是它交换的逻辑我return不掉,我真是谢谢它。然后我就去官网看api,看看有没有提供一个方法能取消掉它的交换逻辑,找半天没找到(我是真的没找到,如果有就是我瞎了),第三方库开发起来确实是方便,但是不灵活也是真的。这种简单的逻辑完全可以自己封装一个拖拽列表嘛,啊你说你熟悉?可以参考下我之前的文章。(图穷匕见了属于是,燕国的地图真长)
没有发现取消交换的api,但是发现提供了一个onMove回调方法里面支持使用return来阻止后续回调的发生。那我就把判断逻辑放到onMove里面,这样就不会触发onEnd也不会走交换逻辑了。好就这么改!
改完后发现,人生不如意啊,确实交换逻辑没执行,但这什么玩意。原来是onMove只要处于移动的状态就一直会触发,触发频率非常高。每次触发都会走一次判断逻辑有未保存项就警告一次。
但是如果不松手 这时候onMove会不停的提示message ,没办法出此下策封装了一个单例模式的message,并写一个节流函数控制警告提示的速度。解决问题。
总结
这可能不是最好的解决方法,但是效果看上去还行。这就是我解决bug的全过程,简单的功能还是尽量不要使用第三方的库来实现,我们组长总是不爱使用第三方的库,类似这种拖拽都是自己封装的。刚开始我还不以为然,今天终于踩坑了,有时候它提供给我们的api不足以满足我们所有的需求。
首次使用单例模式解决问题,纪录一下。
希望大家能有所收获!