From 90000f39f6e113d586b1b455c6c1e7b02aaee1fb Mon Sep 17 00:00:00 2001 From: morning-star <26325820+Sight-wcg@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:10:49 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(table):=20=E6=96=B0=E5=A2=9E=20`table.?= =?UTF-8?q?updateRow`=E6=96=B9=E6=B3=95=20(#1540)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(table): 新增 `table.updateRow` 方法 * refactor * update code * update doc * feat(table): 新增 `table.updateTotalRow` * perf(table): 改进 updateRow 渲染性能 * feat(table): col.totalRow 支持函数,改进 updateTotalRow 参数 * feat(table): 新增 table.getTotalRow * feat(table): table.getTotalRow 支持获取原始结果 * perf(table): 改进 table.updateRow 性能 * fix: 修复 updateRow 一些问题 * revert: 回退除 table.updateRow 以外的所有改动 REVERT: bc61f9ff08d4e512585b399c0dd41954c3878bd0 1a5258b292c6b67873df35f456883afd3da04cbb 4af5b1cda4d2ce6049f7dfafb25f99a498196bc4 62e551d22bfc8a379c15ce44f290f7ff73dbcb3a 这些方法互相关联,而 totalRow 存在暂时无法解决的问题,故全部回退。后续在其他 PR 中实现。 * refactor(table): updateRow options.row 重命名为 options.data --- docs/table/index.md | 36 ++++++++++++++ src/modules/table.js | 116 +++++++++++++++++++++++++++++-------------- 2 files changed, 116 insertions(+), 36 deletions(-) diff --git a/docs/table/index.md b/docs/table/index.md index 1a3ac49d..25179bc8 100644 --- a/docs/table/index.md +++ b/docs/table/index.md @@ -28,6 +28,7 @@ toc: true | [table.reload(id, options, deep)](#table.reload) | 表格完整重载。 | | [table.reloadData(id, options, deep)](#table.reloadData) 2.7+ | 表格数据重载。 | | [table.renderData(id)](#table.renderData) 2.8.5+ | 重新渲染数据。 | +| [table.updateRow(id, opts)](#table.updateRow) 2.9.4+ | 更新指定行数据。 | | [table.checkStatus(id)](#table.checkStatus) | 获取选中行相关数据。 | | [table.setRowChecked(id, opts)](#table.setRowChecked) 2.8+ | 设置行选中状态。 | | [table.getData(id)](#table.getData) | 获取当前页所有行表格数据。 | @@ -313,6 +314,41 @@ data.splice(newIndex, 0, item[0]); table.renderData('test'); ``` +

更新指定行数据 2.9.4+

+ +`table.updateRow(id, opts);` +- 参数 `id` : table 渲染时的 `id` 属性值 +- 参数 `opts` : 更新指定行时的可选属性,详见下表 + +| opts | 描述 | 类型 | 默认值 | +| --- | --- | --- | --- | +| index | 行索引 | number | - | +| data | 行数据 | object | - | +| related | 是否更新其他包含自定义模板且可能有所关联的列视图 | boolean/function | - | + +该方法用于更新指定行数据。 + +```js +// 渲染 +table.render({ + elem: '', // 绑定元素选择器 + id: 'test', // 自定义 id 索引 + // 其他属性 … +}); + +// 更新指定行数据 +table.updateRow('test', { + index: 0, + data: { + id: 1, + username: 'name' + } + // 是否更新关联的列视图 + related: function(field, index){ + return ['score', '5'].indexOf(field) !== -1; + } +}); +```

获取选中行

diff --git a/src/modules/table.js b/src/modules/table.js index 94011e7c..d3c8f515 100644 --- a/src/modules/table.js +++ b/src/modules/table.js @@ -1527,6 +1527,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){ form.render(type, filter); }; + // 定向渲染表单 + Class.prototype.renderFormByElem = function(elem){ + layui.each(['input', 'select'], function(i, formType){ + form.render(elem.find(formType)); + }) + }; + // 同步全选按钮状态 Class.prototype.syncCheckAll = function(){ var that = this; @@ -1886,6 +1893,73 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){ that.layFixRight.css('right', scrollWidth - 1); }; + /** + * @typedef updateRowOptions + * @prop {number} index - 行索引 + * @prop {Object.} data - 行数据 + * @prop {boolean | ((field, index) => boolean)} [related] - 更新其他包含自定义模板且可能有所关联的列视图 + */ + /** + * 更新指定行 + * @param {updateRowOptions | updateRowOptions[]} opts + * @param {(field: string, value: any) => void} [callback] - 更新每个字段时的回调函数 + */ + Class.prototype.updateRow = function(opts, callback){ + var that = this; + var ELEM_CELL = '.layui-table-cell'; + var opts = layui.type(opts) === 'array' ? opts : [opts]; + var dataCache = table.cache[that.key] || []; + + var update = function(opt){ + var index = opt.index; + var row = opt.data; + var related = opt.related; + + var data = dataCache[index] || {}; + var tr = that.layBody.find('tr[data-index="' + index + '"]'); + + // 更新缓存中的数据 + layui.each(row, function (key, value) { + data[key] = value; + callback && callback(key, value); + }); + + // 更新单元格 + that.eachCols(function (i, item3) { + var field = String(item3.field || i); + var shouldUpdate = field in row || ((typeof related === 'function' ? related(field, i) : related) && (item3.templet || item3.toolbar)); + if(shouldUpdate){ + var td = tr.children('td[data-field="' + field + '"]'); + var cell = td.children(ELEM_CELL); + var content = data[item3.field]; + cell.html(parseTempData.call(that, { + item3: item3, + content: content, + tplData: $.extend({ + LAY_COL: item3, + }, data) + })); + td.data("content", content); + that.renderFormByElem(cell); + } + }); + } + + layui.each(opts, function(i, opt){ + update(opt); + }); + }; + + /** + * 更新指定行 + * @param {string} id - table ID + * @param {updateRowOptions | updateRowOptions[]} options + */ + table.updateRow = function (id, options){ + var that = getThisTable(id); + return that.updateRow(options); + } + // 事件处理 Class.prototype.events = function(){ var that = this; @@ -2229,43 +2303,13 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){ }, update: function(fields, related){ // 修改行数据 fields = fields || {}; - layui.each(fields, function(key, value){ - var td = tr.children('td[data-field="'+ key +'"]'); - var cell = td.children(ELEM_CELL); // 获取当前修改的列 - - // 更新缓存中的数据 - data[key] = obj.data[key] = value; - - // 更新相应列视图 - that.eachCols(function(i, item3){ - if(item3.field == key){ - cell.html(parseTempData.call(that, { - item3: item3 - ,content: value - ,tplData: $.extend({ - LAY_COL: item3 - }, data) - })); - td.data('content', value); - } - // 更新其他包含自定义模板且可能有所关联的列视图 - else if(related && (item3.templet || item3.toolbar)){ - var thisTd = tr.children('td[data-field="'+ (item3.field || i) +'"]'); - var content = data[item3.field]; - - thisTd.children(ELEM_CELL).html(parseTempData.call(that, { - item3: item3 - ,content: content - ,tplData: $.extend({ - LAY_COL: item3 - }, data) - })); - thisTd.data('content', content); - } - }); + that.updateRow({ + index: index, + data: fields, + related: related + }, function(key, value){ + obj.data[key] = value; }); - - that.renderForm(); }, // 设置行选中状态 setRowChecked: function(opts){ From 23bf960a2a740bf5916010a6e29138d93b7cea87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B4=A4=E5=BF=83?= <3277200+sentsim@users.noreply.github.com> Date: Thu, 18 Jan 2024 13:38:21 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix(table):=20=E4=BF=AE=E5=A4=8D=20Chrome?= =?UTF-8?q?=20DevTools=20=E5=AE=A1=E6=9F=A5=20iframe=20=E4=B8=AD=20table?= =?UTF-8?q?=20=E5=85=83=E7=B4=A0=E6=97=B6=E5=AF=BC=E8=87=B4=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=B4=A9=E6=BA=83=E7=9A=84=E9=97=AE=E9=A2=98=20(#1571?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/table.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/modules/table.js b/src/modules/table.js index d3c8f515..871615b2 100644 --- a/src/modules/table.js +++ b/src/modules/table.js @@ -1757,7 +1757,24 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){ lay.getStyleRules(style, function(item){ if (item.selectorText === ('.laytable-cell-'+ key)) { - return callback(item), true; + callback(item); + + /* 以下代码为防止 Chrome DevTools 审查 iframe 中的 table 元素时出现的页面崩溃 + * closes https://gitee.com/layui/layui/issues/I8N08M + * 具体原因不明,可能是初始操作 cssRules 触发了 DevTools inspect 的解析报错 + * 后续若浏览器本身修复了该问题,下述补丁也将会剔除 + */ + (function PatcheToCssRulesInDevTools(){ + if (self === parent) return; + var input = lay.elem('input', { + style: 'position: absolute; left: 0; top: 0; opacity: 0.01;' + }); + document.body.appendChild(input); + input.focus(); + document.body.removeChild(input); + })(); + + return true; } }); };