在没有angular和vue等框架之前,jQuery可算得上是前端开发界的一姐了,只要稍微复杂一点的项目,基本上都会用到它。而layer作为一个基于jQuery开发的插件,不仅美观,而且功能足够完善,基本成为了弹窗的完美解决方案。即便是如今双向数据绑定盛行,对很多开发后台管理的后端人员来说,layui依然是个不错的选择。
但是在layer的使用中,有一点不太友好,并且使用的地方还比较多,就是我们弹出一个弹框,一般以填写内容的表单居多(比如新增和编辑),我们的弹框下边会有两个按钮,确定和取消。默认情况下,我们点击这两个按钮,都会关闭弹层,但我们却无法判断点击的是关闭按钮还是取消按钮。要知道,这个判断对我们来说,特别的重要。比如编辑数据,点击确定要求我们关闭弹层、发送请求、刷新列表,而取消我们则只需关闭弹层。而layer自带的关闭按钮和点击遮罩关闭,按道理应该和我们点击取消的时候一样,直接关闭弹窗,没有任何其他操作。
除了上面提到的情况之外,我们还可能弹出的是一个嵌套的iframe,需要在关闭弹层时拿到填写的表单数据以供上层页面使用。
针对上述问题,个人觉得,对layer的关闭方法传递一个参数,是非常有必要的。正好公司的项目在开发时也遇到了类似的问题,故个人花了一点时间,把layer的源码改了一下,支持关闭传递参数。取消按钮,关闭按钮和点击阴影关闭时,都会传递一个false,只有点击确定按钮时才会得到true。并且,当我们手动调用layer.close(index)时,可传递第二个参数,已解决在关闭弹层时想拿到弹层表单数据的需求。
在说改源码之前,我们先理一下layer的关闭逻辑,以方便大家自己去做更灵活的扩展,或者在版本更新后有自己去改动它的能力。从源码得知,layer的所有关闭弹层方法,其实在内部都是调用的layer.close方法,而我们配置的end函数,就是在layer.close方法里的所有代码执行完之后调用的。这里好就好在close方法是统一的接口,我们可以减少很多工作量,因为我们只需改动close方法即可。直接看代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//关闭layer总方法 layer.close = function(index,tag){ /*================close方法添加一个多余的参数tag,可以让我们自己传参================*/ var layero = $('#'+ doms[0] + index), type = layero.attr('type'), closeAnim = 'layer-anim-close'; if(!layero[0]) return; var WRAP = 'layui-layer-wrap', remove = function(){ if(type === ready.type[1] && layero.attr('conType') === 'object'){ layero.children(':not(.'+ doms[5] +')').remove(); var wrap = layero.find('.'+WRAP); for(var i = 0; i < 2; i++){ wrap.unwrap(); } wrap.css('display', wrap.data('display')).removeClass(WRAP); } else { //低版本IE 回收 iframe if(type === ready.type[2]){ try { var iframe = $('#'+doms[4]+index)[0]; iframe.contentWindow.document.write(''); iframe.contentWindow.close(); layero.find('.'+doms[5])[0].removeChild(iframe); } catch(e){} } layero[0].innerHTML = ''; layero.remove(); } /*================把我们自己传递的参数传到end方法里,在end中我们就可以获取到自己传递的参数进行判断================*/ typeof ready.end[index] === 'function' && ready.end[index](tag); delete ready.end[index]; }; //... }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//按钮关闭时,做判断 layero.find('.'+ doms[6]).children('a').on('click', function(){ var index = $(this).index(); if(index === 0){ if(config.yes){ config.yes(that.index, layero) } else if(config['btn1']){ config['btn1'](that.index, layero) } else { layer.close(that.index,1);/*======默认传1========*/ } } else { var close = config['btn'+(index+1)] && config['btn'+(index+1)](that.index, layero); close === false || layer.close(that.index,0);/*=======默认传0=======*/ } }); //取消 function cancel(){ var close = config.cancel && config.cancel(that.index, layero); close === false || layer.close(that.index,0); /*=======默认传0=======*/ } //右上角关闭回调 layero.find('.'+ doms[7]).on('click', cancel); //点遮罩关闭 if(config.shadeClose){ $('#layui-layer-shade'+ that.index).on('click', function(){ layer.close(that.index,0);/*======默认传0========*/ }); } |
有了上面的改动,我们就可以随心所欲的做我们想做的事了。比如,我们想弹出一个iframe页面,然后关闭时获取里面的表单数据,就可以这样:
iframe里的js代码:
1 2 3 4 |
form.on('submit(addForm)', function (data) { parent.layer.close(parent.layer.getFrameIndex(window.name),data.field); return false; }); |
打开弹层页的js代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
layer.open({ //... end: function(data) { console.log(data);//这里的data就是iframe弹层里的表单对象 $.ajax({ //... data:data, success:function(){ //... }, //... }) } }); |
好了,关于layer的判断方法解决,就介绍到这里。其实呢,如果你有时间,看源码是一件很有趣的事,特别是有些插件,可能对我们的业务来说很有用,就是个别地方不太符合我们的项目,这个时候,往往就需要我们进行源码修改或者二次封装。虽然不提倡改源码的方式(主要原因就是版本迭代问题),但如果针对单一的某个系统,稍微改一下源码,就能减少大量的工作量,并且满足需求,带来便利,改一下又有何不可呢?其实更客观一点,我们可以称之为定制化插件。但如果你做的是一个开源框架,用的人很多,就不建议这种做法了,因为时间一长,大家引入的版本不一致,就可能出现各种问题。之前曾给element ui改过源码,就是为Dialog弹层添加了一个上下居中的参数,可是因为产品规范的原因,被拒绝了。
最后,附上一个我改好的版本:https://github.com/lilaobiao/layui/tree/master/lay/modules,下载下来替换掉原来的layer.js即可用,不过得注意版本问题。之前也讲过一篇关于layui表单数据智能处理的办法,如果觉得我的文章对你有帮助,可以考虑在下载时顺便给我的github给个star。去年一年没更新博客,今年争取多更新,一是个人工作经验的总结,二是希望能把我所知道的分享给他人,共同进步。大牛人物请无视我的这段话。
发表评论