一、遇到的问题及解决方案(心得) 1.让select下拉列表项目中的文字居中 ~~~ .layui-form-select dl dd{ text-align: center; } ~~~ 2.让表单label标签的宽度自动取其自身宽度 ~~~ .layui-form-pane .layui-form-label { width: auto; } ~~~ 3.数据表格行背景色设置 数据表格中有开启隔行变色的效果,设置隔行变色的背景如下: ~~~ .layui-table[lay-even] tr:nth-child(even){ background-color: #fafafa; } ~~~ 设置鼠标悬浮的行背景色: ~~~ .layui-table tbody tr:hover,.layui-table-hover{ background-color: #e4efff!important; } ~~~ 设置鼠标点击(或选择)某行后的背景色: ~~~ .layui-table-click{ background-color:#f2f2f2!important; } ~~~ 4.让弹出层信息框宽度自动取其自身宽度 ~~~ .layui-layer-msg{ min-width: auto!important; } ~~~ 5.让弹出层按钮分散居中对齐,并让其中表单元素宽度自动调整 这个稍稍有些复杂,直接上代码 CSS: ~~~ .layui-form-pane .layui-form-label { width: auto; } .layui-form-radio{ padding-right: 0; margin-right:0; } .layui-form-select dl dd{ text-align: center; } .layui-form-pane .layui-input-inline, .layui-form-pane .layui-inline,.layui-form-pane .layui-form-mid { margin-right: 0; } .layui-form-item .layui-input-block{ float:left; margin-left: 0!important; } ~~~ HTML/JS ~~~ <form class="layui-form layui-form-pane" id="layerform" style="display: none;padding:5px"> <input type="hidden" name="id"> <div class="layui-form-item" widthoffset="15"> <div class="layui-inline"> <label class="layui-form-label">姓名</label> <div class="layui-input-inline col12"> <input type="text" name="name" autocomplete="off" placeholder="请输入姓名" class="layui-input" lay-verify="required" lay-verType="tips"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">年龄</label> <div class="layui-input-inline" width="45"> <input type="text" name="age" autocomplete="off" class="layui-input" lay-verify="positiveInteger" lay-verType="tips"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">性别</label> <div class="layui-input-inline" width="70"> <select name="sex"> <option value="-1">保密</option> <option value="1">男</option> <option value="0">女</option> </select> </div> </div> <div class="layui-inline"> <label class="layui-form-label">是否饮酒</label> <div class="layui-input-inline" width="132"> <input type="radio" name="drink" value="1" title="是"> <input type="radio" name="drink" value="0" title="否" checked> </div> </div> </div> <div class="layui-form-item" widthoffset="15"> <div class="layui-inline"> <label class="layui-form-label">身高(cm)</label> <div class="layui-input-inline" width="45"> <input type="text" name="height" autocomplete="off" class="layui-input" lay-verify="positiveInteger" lay-verType="tips"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">体重(kg)</label> <div class="layui-input-inline" width="45"> <input type="text" name="weight" autocomplete="off" class="layui-input" lay-verify="positiveInteger" lay-verType="tips"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">电话</label> <div class="layui-input-inline col12"> <input type="text" name="telphone" autocomplete="off" placeholder="手机或电话" class="layui-input"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">是否吸烟</label> <div class="layui-input-inline" width="132"> <input type="radio" name="smoke" value="1" title="是"> <input type="radio" name="smoke" value="0" title="否" checked> </div> </div> </div> <div class="layui-form-item" widthoffset="10"> <div class="layui-inline"> <label class="layui-form-label">微信</label> <div class="layui-input-inline col4"> <input type="text" name="wechat" autocomplete="off" placeholder="请输入微信" class="layui-input"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">QQ</label> <div class="layui-input-inline col4"> <input type="text" name="qq" autocomplete="off" placeholder="请输入QQ" class="layui-input"> </div> </div> <div class="layui-inline"> <label class="layui-form-label">电子邮箱</label> <div class="layui-input-inline col4"> <input type="text" name="email" autocomplete="off" placeholder="请输入Email" class="layui-input" lay-verify="email" lay-verType="tips"> </div> </div> </div> <div class="layui-form-item" widthoffset="4"> <label class="layui-form-label">地址</label> <div class="layui-input-block col12"> <input type="text" name="address" autocomplete="off" placeholder="请输入地址" class="layui-input"> </div> </div> <div class="layui-form-item" widthoffset="4"> <label class="layui-form-label">备注</label> <div class="layui-input-block col12"> <input type="text" name="comment" autocomplete="off" class="layui-input"> </div> </div> <!--<div class="layui-form-item btns"> <div class="layui-input-block"> <button class="layui-btn layui-btn-radius" lay-submit lay-filter="layerForm">确定</button> <button class="layui-btn layui-btn-radius layui-btn-primary cancel" type="button">取消</button> </div> </div>--> </form> <script> //按钮分散对齐 function locateBtns(layero, $) { var layerBtns = layero.find(".layui-layer-btn a"); var btns = layero.find(".btns .layui-btn"); var sumWidth = 0; layui.each(layerBtns, function (i, e) { sumWidth += $(e).outerWidth(); }); var gap = (layero.width() - sumWidth) / (layerBtns.length + 1); layui.each(layerBtns, function (i, e) { $(e).css({ position: "relative", left: gap * (i + 1) }); }); sumWidth = 0; layui.each(btns, function (i, e) { sumWidth += $(e).outerWidth(); }); var pLeft = parseInt(layero.find(".layui-layer-wrap").css("padding-left")); var pRight = parseInt(layero.find(".layui-layer-wrap").css("padding-right")); gap = (layero.width() - pLeft - pRight - sumWidth) / (btns.length + 1); layui.each(btns, function (i, e) { $(e).css({ position: "relative", left: gap * (i + 1) }); }); } //表单元素宽度自适应 function resizeForm(layero, $) { var items=layero.find(".layui-form-item"); layui.each(items,function (i,e) { var widthoffset=$(e).attr("widthoffset"); var widthSum=0; layui.each($(e).find(".layui-form-label"),function (i,e) { widthSum+=$(e).outerWidth(true); }); layui.each($(e).find(".layui-input-inline[width]"),function (i,e) { var jdom=$(e); jdom.width(jdom.attr("width")); widthSum+=jdom.outerWidth(true); }); var totalWidth=$(e).width()-widthSum; if(widthoffset){ totalWidth-=widthoffset; } for (var i = 0; i < 12; i++) { var cells=$(e).find(".col"+(i+1)); cells.width(totalWidth*(i+1)/12); } }); locateBtns(layero, $); } //入口函数,绑定事件并调用弹出层 function layerForm(layer,jquery,options){ var resizing=options.resizing; var full=options.full; var restore=options.restore; var success=options.success; var $=jquery; options.btnAlign="l"; options.resizing=function(layero){ resizeForm(layero, $); resizing && resizing(layero); } options.full=function(layero){ resizeForm(layero, $); full && full(layero); } options.restore=function(layero){ resizeForm(layero, $); restore && restore(layero); } options.success=function(layero, index){ resizeForm(layero, $); success && success(layero, index); } return layer.open(options); } //弹出层调用 var index=layerForm(layer,$,{ title:"查看", content:$("#layerform"), type:1, area: "710px", maxmin: true, btn:['确定','取消'] }); </script> ~~~ 6.让加载层文字居中,宽度自适应不会换行 ~~~ .layui-layer-loading .layui-layer-content{ padding-top: 40px!important; width: auto!important; height: auto!important; background-position-x: 50%!important; color:#FF5722; } ~~~ 7.修复数据表格初始化时不会显示加载提示BUG 版本layui-v2.2.5 layui table首次加载没有显示loading,通过修改源码可以实现 方法:在layui.all.js文件中的下面位置添加js代码 ~~~ if(n.url){i=i||a.loading();} ~~~ 8.表单增强插件,主要使用表单自动填充功能 首先这里须要修改几行代码,否则无法在同一个页面使用该插件同时操作多个表单(多个EnhanceForm对象)! 代码中原有前10行内容如下: ~~~ layui.define(['jquery', 'form'], function(exports) { var $ = layui.jquery, form = layui.form, formObj, hint = layui.hint(); var EnhanceForm = function(options) { this.options = options; formObj = $(options.elem); }; ~~~ 将其替换为如下内容: ~~~ layui.define(['jquery', 'form'], function(exports) { var $ = layui.jquery, form = layui.form, hint = layui.hint(); var EnhanceForm = function(options) { this.options = options; this.formObj = $(options.elem); }; ~~~ 并且将后续代码中出现的所有formObj变量改为this.formObj 同时我在其基础上添加了几个功能: ~~~ //将表单转化为json对象 EnhanceForm.prototype.serializeJson = function() { var serializeObj={}; var array=this.formObj.serializeArray(); var str=this.formObj.serialize(); layui.each(array,function(i,e){ if(serializeObj[e.name]){ if($.isArray(serializeObj[e.name])){ serializeObj[e.name].push(e.value); }else{ serializeObj[e.name]=[serializeObj[e.name],e.value]; } }else{ serializeObj[e.name]=e.value; } }); return serializeObj; }; //禁用所有表单元素 EnhanceForm.prototype.disableAll = function() { var eles=this.formObj.find("input,select,textarea"); eles.attr("disabled","disabled"); form.render(); }; //启用所有表单元素 EnhanceForm.prototype.enableAll = function() { var eles=this.formObj.find("input,select,textarea"); eles.removeAttr("disabled"); form.render(); }; ~~~ 9.form表单提交事件bug 表单绑定提交事件如下: ~~~ form.on('submit(filterName)', function(data){ }); ~~~ 其中参数data.field包含当前表单容器的全部表单字段,名值对形式:{name: value} 但是如果表单中含有checkbox则会出现bug,如: 表单中含有如下3个checkbox: ~~~ <input type="checkbox" name="interest" title="写作" value="writing"> <input type="checkbox" name="interest" title="音乐" value="music"> <input type="checkbox" name="interest" title="电影" value="movie"> ~~~ 用户同时选中“写作”、“电影”两项 此时data.field中只有{interest:"movie"}这一项。 解决方案: 修改layui的form模块源码form.js 原来477-478行代码如下: ~~~ if(/^checkbox|radio$/.test(item.type) && !item.checked) return; field[item.name] = item.value; 将其修改为: if(/^checkbox|radio$/.test(item.type) && !item.checked) return; if(field[item.name]){ if(!(field[item.name] instanceof Array)){ field[item.name]=[field[item.name]]; } field[item.name].push(item.value); }else{ field[item.name] = item.value; } ~~~ 这是data.field中为{interest:["writing","movie"]} PS:如果你的表单中有多个name相同的其他类型表单元素也同理!同时不会影响类似于下面这种数组name表单: ~~~ <input type="text" name="test[0]"> <input type="text" name="test[1]"> <input type="text" name="test[2]"> ~~~ 10.关于laydate控件 首先,用一个页面绑定多个laydate控件bug,这个问题貌似有很多人提出过,其中有人已经给出了解决方案:http://fly.layui.com/jie/14329/。 不过貌似版本升级后源码已经发生了变化,现在需要做如下修改,原来的laydate.js的1802-1806行代码如下: ~~~ if(e.target === options.elem[0] || e.target === options.eventElem[0] || e.target === lay(options.closeStop)[0]){ return; } ~~~ 修改后如下: ~~~ var elem=options.elem.some(function (el) { return e.target === el }); var eventElem=options.eventElem.some(function (el) { return e.target === el }); var closeStop=lay(options.closeStop).some(function (el) { return e.target === el }); if(elem||eventElem||closeStop){ return; } ~~~ 有时还会报如下错误: ~~~ laydate.js:797 Uncaught TypeError: Cannot read property 'appendChild' of undefined at Class.hint (VM13097 laydate.js:797) at Class.checkDate (VM13097 laydate.js:922) at Class.remove (VM13097 laydate.js:742) at HTMLDocument.<anonymous> (VM13097 laydate.js:1809) ~~~ 可以修改源码修复,源码834-837行如下: ~~~ Class.prototype.checkDate = function(fn){ var that = this ,thisDate = new Date() ,options = that.config ~~~ 添加一个非空判断,修改如下: ~~~ Class.prototype.checkDate = function(fn){ if(!this.elem){ return ; } var that = this ,thisDate = new Date() ,options = that.config ~~~ 另外,我还在原有done、change回调基础上添加了一个参数 ~~~ done: function(dom,value, date, endDate){ console.log(dom);//触发当前时期选择事件的dom对象 console.log(value); //得到日期生成的值,如:2017-08-18 console.log(date); //得到日期时间对象:{year: 2017, month: 8, date: 18, hours: 0, minutes: 0, seconds: 0} console.log(endDate); //得结束的日期时间对象,开启范围选择(range: true)才会返回。对象成员同上。 } ~~~ 源码1473行如下: ~~~ param = param || 【that.parse(), start, end】;//(这里貌似是社区编辑器的一个bug,源码中【】符号为英文中括号[]) ~~~ 修改如下: ~~~ param = param || 【that.bindElem,that.parse(), start, end】;//(这里貌似是社区编辑器的一个bug,源码中【】符号为英文中括号[]) ~~~ 11.调整layui-btn按钮之间的间距 ~~~ .layui-btn+.layui-btn{ margin-left: 1px; } ~~~ 12.关于数据表格修改行数据后模版渲染的BUG 数据表格可以定义模板以便以自己的方式显示数据,模板有三种方式:绑定模版选择器、函数转义、直接赋值模版字符 如果使用函数转义如: ~~~ {field:'sex', title: '性别',width:60,align:'center' , templet:function(d){ if(d.sex==1){ return "男"; }else if(d.sex==0){ return "女"; }else{ return "保密"; } } } ~~~ 并且此时再修改行数据时就会出现BUG,修改后性别直接显示1、0、-1,而不会经过函数转义了。 使用绑定模版选择器或直接赋值模版字符不会出现此BUG 修改table.js源码如下: 源码1140行如下: templet ? laytpl($(templet).html() || value).render(data) : value 将其修改为: templet ?(typeof templet === 'function'?templet(data):laytpl($(templet).html() || value).render(data)):value 13.关于数据表格排序 目前数据表格排序功能最多只能针对某一列做排序,但是有时可能需要同时对多列排序,并且需要根据排序参数重新请求后台,为了实现这个功能,我对table.js源码修改如下: 源码403-405行如下: ~~~ if(typeof options.initSort === 'object'){ that.sort(options.initSort.field, options.initSort.type); } ~~~ 修改如下: ~~~ if(options.initSort instanceof Array){ layui.each(options.initSort,function (i,e) { that.sort(e.field, e.sort); }) } ~~~ 源码416行如下: `params[request.limitName] = options.limit;` 在其后插入如下代码: ~~~ if(options.initSort!=null && options.initSort.length>0){ params["sorts"]=JSON.stringify(options.initSort); } ~~~ 源码694行如下: `that.layHeader.find('th').find(ELEM_SORT).removeAttr('lay-sort'); //清除其它标题排序状态` 将其删除或注释 源码702-705行如下: ~~~ that.sortKey = { field: field ,sort: type }; ~~~ 在其后插入如下代码: ~~~ var sortIndex=-1; if(options.initSort instanceof Array){ layui.each(options.initSort,function (i,e) { if(e.field==field){ sortIndex=i; return false; } }); }else{ options.initSort=[]; } if(sortIndex==-1){ options.initSort.push(that.sortKey); sortIndex=options.initSort.length-1; } if(type){ options.initSort[sortIndex].sort=type; }else{ options.initSort.splice(sortIndex,1); } ~~~ 源码719-724行如下: ~~~ if(formEvent){ layui.event.call(th, MOD_NAME, 'sort('+ filter +')', { field: field ,type: type }); } ~~~ 修改如下: ~~~ if(formEvent){ layui.event.call(th, MOD_NAME, 'sort('+ filter +')', { field: field ,type: type ,sorts: options.initSort }); } }; ~~~ 修改后数据表格可以同时对多列排序,并结合排序事件监听实现后台排序。 同时数据表格在翻页或重载时,会自动以sorts为键值自动向后台传递排序请求参数,形如:{sorts:[{"field":"height","sort":"asc"},{"field":"age","sort":"desc"}]} 并且排序事件的参数obj会增加一个属性sorts,内容与排序请求参数一致,如: ~~~ table.on('sort(test)', function(obj){ //注:tool是工具条事件名,test是table原始容器的属性 lay-filter="对应的值" console.log(obj.field); //当前排序的字段名 console.log(obj.type); //当前排序类型:desc(降序)、asc(升序)、null(空对象,默认排序) console.log(this); //当前排序的 th 对象 console.log(obj.sorts)//排序参数 //尽管我们的 table 自带排序功能,但并没有请求服务端。 //有些时候,你可能需要根据当前排序的字段,重新向服务端发送请求,从而实现服务端排序,如: table.reload('idTest'); }); ~~~ 二、建议 我原来是使用EasyUI的,所以初次使用layui时很多思路还是和原来一样,但是有时候layui很多功能没有EasyUI完善,用起来就很不爽,希望心姐多多借鉴一下EasyUI的做法 1.为什么不把表单元素设计成类似于下面的形式 ~~~ <div class="layui-form-item"> <div class="layui-input-block"> <label class="layui-form-label">地址 <input type="text" name="address" autocomplete="off" placeholder="请输入地址" class="layui-input"> </label> </div> </div> ~~~ 这样用户直接点击标签的文字光标就能直接定位到相应的文本框,用户体验更好 2.添加一个类似于如下的日历控件 3.关于form表单 EasyUI中有个form模块可以直接以ajax方式提交表单及自动填充表单(自动渲染),非常简单两行代码就搞定了,现在layui实现相同功能需要自己手动写代码或依赖大量插件辅助,很麻烦!我在EnhanceForm插件中已经实现了简单的ajax提交表单,不过没有充分测试,心姐可以完善后整合到layui中! 现在表单验证只能在点击提交按钮时提交表单时才会触发,但是有时候项目中表单验证并不是通过表单提交触发的,程序员希望自己手动调用js方法触发验证效果,所以建议为form添加一个validate方法,用于在表单验证框架基础上做表单验证,返回true、false表示验证是否通过,同时如果验证不通过自动显示提示等。 4.建议为数据表格增加一个添加行的方法(类似于EasyUI的appendRow、insertRow方法) 5.为数据表格增加获取所有行数据的方法(类似于EasyUI的getRows方法) 6.数据表格列宽度权重 建议为数据表格增加一个列宽度设置为权重的功能,假设数据表格共A、B、C、D四列,其中A、C列为固定宽度50px,B列宽度权重为1,D列宽度权重为2,则渲染效果为,B列宽度=(数据表格总宽度-100px)*1/3,D列宽度=(数据表格总宽度-100px)*2/3 7.添加功能:数据表格数据行区域也能实现类似于复杂表头跨行跨列的功能 8.单元格编辑类型目前只支持:text(输入框),建议添加下拉列表、日期选择、文件上传等类型,或者开发接口可以让用户自定义编辑器,同时可以添加验证规则,添加进入编辑状态前的触发事件,添加让单元格进入编辑状态的方法 9.添加功能:弹出层左上角标题文字旁也可以设置一个可爱的小图标^_^ 10.添加类似于EasyUI中ComboTree(树形下拉框)和ComboGrid(数据表格下拉框)控件 11.添加属性:数据表格开启复选框时,可以设置singleSelect模式,即只允许选择一行 12.添加属性:数据表格开启复选框时,可以设置checkOnSelect,如果为true,当用户点击行的时候该复选框就会被选中或取消选中。如果为false,当用户仅在点击该复选框的时候才会被选中或取消。