From ba5f7891d1bceac85f5bade55adbaae10a206379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B2=81=E6=9C=88=E5=B0=8F=E5=81=B7?= <470459819@qq.com> Date: Sun, 19 Jun 2022 02:10:15 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=83=A8=E5=88=86bug?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=E6=96=B0=E5=A2=9E=E4=B8=80=E4=BA=9B=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=201=E3=80=81layui=20=E6=B7=BB=E5=8A=A0unuse=E6=96=B9?= =?UTF-8?q?=E6=B3=95=E7=94=A8=E4=BA=8E=E6=B3=A8=E9=94=80=E5=B7=B2=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E7=9A=84=E6=A8=A1=E5=9D=97=202=E3=80=81table=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0reloadData=E6=96=B9=E6=B3=95=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E9=87=8D=E8=BD=BD=E6=95=B0=E6=8D=AE=203=E3=80=81table?= =?UTF-8?q?=20=E4=BF=AE=E5=A4=8Dtable.exportFile=E6=8A=A5=E9=94=99=204?= =?UTF-8?q?=E3=80=81table=20=E6=B7=BB=E5=8A=A0editTrigger=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=EF=BC=8C=E5=8F=AF=E4=BB=A5=E8=AE=BE=E5=AE=9A=E8=A7=A6?= =?UTF-8?q?=E5=8F=91=E5=8D=95=E5=85=83=E6=A0=BC=E7=BC=96=E8=BE=91=E7=9A=84?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E4=B8=BAclick=EF=BC=88=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=EF=BC=89=E6=88=96dblclick=205=E3=80=81form=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0doVerify=E6=96=B9=E6=B3=95=E6=94=AF=E6=8C=81=E4=B8=BB?= =?UTF-8?q?=E5=8A=A8=E8=B0=83=E7=94=A8=E8=A1=A8=E5=8D=95=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E7=89=B9=E5=AE=9A=E8=8C=83=E5=9B=B4?= =?UTF-8?q?=E5=86=85=E8=A1=A8=E5=8D=95=E8=BE=93=E5=85=A5=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=206=E3=80=81form=20form.render=E6=96=B9=E6=B3=95=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=AF=B9=E7=89=B9=E5=AE=9A=E8=8A=82=E7=82=B9=E7=9A=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E6=94=AF=E6=8C=81=EF=BC=8C=E9=99=A4=E4=BA=86?= =?UTF-8?q?=E4=BB=A5=E5=89=8D=E8=AE=BE=E7=BD=AE=E7=B1=BB=E5=9E=8B=E5=92=8C?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E8=8C=83=E5=9B=B4=E8=BF=98=E5=8F=AF=E4=BB=A5?= =?UTF-8?q?=E7=9B=B4=E6=8E=A5=E5=AF=B9=E9=9C=80=E8=A6=81=E6=B8=B2=E6=9F=93?= =?UTF-8?q?=E7=9A=84=E8=8A=82=E7=82=B9=E5=AF=B9=E8=B1=A1=E8=BF=9B=E8=A1=8C?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=207=E3=80=81form=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=E9=AA=8C=E8=AF=81=E5=9C=A8=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E7=AB=AF=E6=A3=80=E9=AA=8C=E5=88=B0=E4=B8=8D=E6=BB=A1=E8=B6=B3?= =?UTF-8?q?=E8=A6=81=E6=B1=82=E7=9A=84=E8=A1=A8=E5=8D=95=E5=85=83=E7=B4=A0?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E7=BA=A2=E6=A1=86=E6=98=BE=E7=A4=BA=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layui.js | 15 ++++++ src/modules/form.js | 113 ++++++++++++++++++++++++++++--------------- src/modules/table.js | 71 +++++++++++++++++++++++---- 3 files changed, 151 insertions(+), 48 deletions(-) diff --git a/src/layui.js b/src/layui.js index f21ef1c..24d6307 100644 --- a/src/layui.js +++ b/src/layui.js @@ -232,6 +232,21 @@ return that; }; + Layui.prototype.unuse = function (apps) { + var that = this; + apps = that.isArray(apps) ? apps : [apps]; + that.each(apps, function (index, item) { + if (!config.status[item]) { + return error('module ' + item + ' is not exist'); + } + delete that[item]; + delete modules[item]; + delete that.modules[item]; + delete config.status[item]; + delete config.modules[item]; + }) + } + //获取节点的 style 属性值 Layui.prototype.getStyle = function(node, name){ var style = node.currentStyle ? node.currentStyle : win.getComputedStyle(node, null); diff --git a/src/modules/form.js b/src/modules/form.js index ea8ab4b..043948e 100644 --- a/src/modules/form.js +++ b/src/modules/form.js @@ -145,19 +145,19 @@ layui.define('layer', function(exports){ }()) ,items = { //输入框 - input: function(){ - var inputs = elemForm.find('input,textarea'); - + input: function(elem){ + var inputs = elem || elemForm.find('input,textarea'); + //初始化全局的 autocomplete options.autocomplete && inputs.attr('autocomplete', options.autocomplete); } //下拉选择框 - ,select: function(){ + ,select: function(elem){ var TIPS = '请选择', CLASS = 'layui-form-select', TITLE = 'layui-select-title' ,NONE = 'layui-select-none', initValue = '', thatInput - ,selects = elemForm.find('select') - + ,selects = elem || elemForm.find('select') + //隐藏 select ,hide = function(e, clear){ if(!$(e.target).parent().hasClass(TITLE) || clear){ @@ -480,13 +480,13 @@ layui.define('layer', function(exports){ } //复选框/开关 - ,checkbox: function(){ + ,checkbox: function(elem){ var CLASS = { checkbox: ['layui-form-checkbox', 'layui-form-checked', 'checkbox'] ,_switch: ['layui-form-switch', 'layui-form-onswitch', 'switch'] } - ,checks = elemForm.find('input[type=checkbox]') - + ,checks = elem || elemForm.find('input[type=checkbox]') + ,events = function(reElem, RE_CLASS){ var check = $(this); @@ -552,10 +552,10 @@ layui.define('layer', function(exports){ } //单选框 - ,radio: function(){ + ,radio: function(elem){ var CLASS = 'layui-form-radio', ICON = ['', ''] - ,radios = elemForm.find('input[type=radio]') - + ,radios = elem || elemForm.find('input[type=radio]') + ,events = function(reElem){ var radio = $(this), ANIM = 'layui-anim-scaleSpring'; @@ -611,34 +611,58 @@ layui.define('layer', function(exports){ }); } }; - type ? ( - items[type] ? items[type]() : hint.error('不支持的 "'+ type + '" 表单渲染') - ) : layui.each(items, function(index, item){ - item(); - }); + if (layui._typeof(type) === 'object') { + // jquery对象 + type.each(function (index, item) { + var elem = $(item); + if (!elem.closest(ELEM).length) { + // 如果不是存在layui-form中的直接跳过 + return; + } + if (item.tagName === 'SELECT') { + items['select'](elem); + } else if (item.tagName === 'INPUT') { + var itemType = item.type; + if (itemType === 'checkbox' || itemType === 'radio') { + items[itemType](elem); + } else { + items['input'](elem); + } + } + }); + } else { + type ? ( + items[type] ? items[type]() : hint.error('不支持的 "'+ type + '" 表单渲染') + ) : layui.each(items, function(index, item){ + item(); + }); + } return that; }; - - //表单提交校验 - var submit = function(){ + + // verifyElem: 要验证的节点或者范围 返回:验证通过返回true,否则返回false + Form.prototype.doVerify = function(verifyElem){ var stop = null //验证不通过状态 - ,verify = form.config.verify //验证规则 - ,DANGER = 'layui-form-danger' //警示样式 - ,field = {} //字段集合 - ,button = $(this) //当前触发的按钮 - ,elem = button.parents(ELEM).eq(0) //当前所在表单域 - ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素 - ,formElem = button.parents('form')[0] //获取当前所在的 form 元素,如果存在的话 - ,filter = button.attr('lay-filter'); //获取过滤器 - - + ,verify = form.config.verify //验证规则 + ,DANGER = 'layui-form-danger' //警示样式 + + if (layui.type(verifyElem) !== 'object') { // 不符合要求的格式直接判通过 + hint.error('doVerify: 参数错误'); + return true; + } + if (!verifyElem.attr('lay-verify')) { + // 验证某个容器内的节点 + verifyElem = verifyElem.find('*[lay-verify]'); + } + //开始校验 layui.each(verifyElem, function(_, item){ var othis = $(this) - ,vers = othis.attr('lay-verify').split('|') - ,verType = othis.attr('lay-verType') //提示方式 - ,value = othis.val(); - + ,verifyStr = othis.attr('lay-verify') || '' + ,vers = verifyStr.split('|') + ,verType = othis.attr('lay-verType') //提示方式 + ,value = othis.val(); + othis.removeClass(DANGER); //移除警示样式 //遍历元素绑定的验证规则 @@ -687,7 +711,7 @@ layui.define('layer', function(exports){ } else { //移动设备定位 $dom.scrollTop(function(){ try { - return (isForm2Elem ? othis.next() : othis).offset().top - 15 + return (isForm2Elem ? othis.next() : othis).focus().offset().top - 15 } catch(e){ return 0; } @@ -701,9 +725,22 @@ layui.define('layer', function(exports){ }); if(stop) return stop; }); - - if(stop) return false; - + + return !stop; + } + + //表单提交校验 + var submit = function(){ + var field = {} //字段集合 + ,button = $(this) //当前触发的按钮 + ,elem = button.parents(ELEM).eq(0) //当前所在表单域 + ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素 + ,formElem = button.parents('form')[0] //获取当前所在的 form 元素,如果存在的话 + ,filter = button.attr('lay-filter'); //获取过滤器 + + //开始校验 + if(!form.doVerify(verifyElem)) return false; + //获取当前表单值 field = form.getValue(null, elem); diff --git a/src/modules/table.js b/src/modules/table.js index 41b1cb4..56b8eba 100644 --- a/src/modules/table.js +++ b/src/modules/table.js @@ -53,6 +53,9 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ ,reload: function(options, deep){ that.reload.call(that, options, deep); } + ,reloadData: function(options, deep){ + table.reloadData(id, options, deep); + } ,setColsWidth: function(){ that.setColsWidth.call(that); } @@ -251,6 +254,7 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ ,loading: true //请求数据时,是否显示 loading ,escape: true // 是否开启 HTML 编码功能,即转义 html 原文 ,cellMinWidth: 60 //所有单元格默认最小宽度 + ,editTrigger: 'click' //单元格编辑的触发方式 ,defaultToolbar: ['filter', 'exports', 'print'] //工具栏右侧图标 ,autoSort: true //是否前端自动排序。如果否,则需自主排序(通常为服务端处理好排序) ,text: { @@ -694,7 +698,11 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ that.layMain.find('tbody').html(''); that.layMain.append(that.layNone = layNone); - + + // 异常情况下对page和total的内容处理 + that.layPage && that.layPage.addClass(HIDE).find('>div').html(''); + that.layTotal && that.layTotal.addClass(HIDE).find('tbody').html(''); + table.cache[that.key] = []; //格式化缓存数据 }; @@ -941,6 +949,7 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ //正常初始化数据渲染 render(); //渲染数据 that.renderTotal(data, totalRowData); //数据合计 + that.layTotal && that.layTotal.removeClass(HIDE); //同步分页状态 if(options.page){ @@ -1697,7 +1706,7 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ }); //单元格单击事件 - that.layBody.on('click', 'td', function(e){ + that.layBody.on(options.editTrigger, 'td', function(e){ var othis = $(this) ,field = othis.data('field') ,editType = othis.data('edit') @@ -1982,8 +1991,6 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ //表格导出 table.exportFile = function(id, data, type){ - var that = this; - data = data || table.clearCacheKey(table.cache[id]); type = type || 'csv'; @@ -2023,8 +2030,8 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ } var content = item1[item3.field] - ,td = that.layBody.find('tr[data-index="'+ i1 +'"]>td'); - + ,td = thatTable.layBody.find('tr[data-index="'+ i1 +'"]>td'); + if(content === undefined || content === null) content = ''; i1 == 0 && dataTitle.push(item3.title || ''); @@ -2046,14 +2053,14 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ }); //表合计 - layui.each(that.dataTotal, function(key, value){ + thatTable && layui.each(thatTable.dataTotal, function(key, value){ fieldsIsHide[key] || dataTotal.push(value); }); return dataTitle.join(',') + '\r\n' + dataMain.join('\r\n') + '\r\n' + dataTotal.join(','); }()); - - alink.download = (config.title || 'table_'+ (config.index || '')) + '.' + type; + + alink.download = (config.title || 'table_'+ (config.index || new Date().getTime())) + '.' + type; document.body.appendChild(alink); alink.click(); document.body.removeChild(alink); @@ -2085,7 +2092,51 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ return thisTable.call(that); }; - + + //需要重新render的参数名单 + var dataParams = ['data', 'url', 'where', 'page', 'request', 'response']; + //重载数据 options只允许跟数据请求相关的配置信息 + table.reloadData = function(id, options, deep){ + var config = getThisTableConfig(id); //获取当前实例配置项 + if (!config) return; + + var that = thisTable.that[id]; + options = options || {}; + + if (options.page !== undefined && !!options.page !== !!config.page) { + // 如果是否分页发生了改变 + hint.error('reloadData不允许对是否分页进行切换(从不分页到分页的切换,反之亦然),如果需要请使用reload重载'); + delete options.page; + } + //过滤options只留下跟数据请求相关的参数 + layui.each(options, function (_key, _value) { + if (dataParams.indexOf(_key) === -1) { + delete options[_key]; + } + }); + if (options.page !== undefined) { // 针对page组件的特殊处理 + if (typeof options.page === 'object') { + options.page.curr && (that.page = options.page.curr); + delete options.elem; + delete options.jump; + } else if (options.page) { + options.page = {}; + } + $.extend(true, that.config, {page: options.page}); + delete options.page; + } + + if (options.data && options.data.constructor === Array) delete that.config.data; + deep ? $.extend(true, that.config, options) : $.extend(that.config, options); + if (!that.config.page) { + that.page = 1; + } + that.loading(); + that.pullData(that.page); + return thisTable.call(that); + } + + //核心入口 table.render = function(options){ var inst = new Class(options);