Browse Source

refactor(table): 重构 table.setRowChecked() 方法 (#2146)

* refactor(table): 重构 table.setRowChecked() 方法

* feat: 进一步优化 `table.setRowChecked()`
fix: 修复单选时未移除其他行数据选中状态的问题

* refactor: 剔除多余判断

* docs: 优化 checked 选项说明
pull/2171/head
贤心 3 months ago committed by GitHub
parent
commit
4545ec151a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 4
      docs/table/index.md
  2. 2
      examples/table-test.html
  3. 87
      src/modules/table.js

4
docs/table/index.md

@ -381,8 +381,8 @@ console.log(tableStatus.isAll ) // 表格是否全选
| opts | 描述 | 类型 | 默认值 |
| --- | --- | --- | --- |
| type | 选中方式。可选值: `checkbox,radio` | string | `checkbox` |
| index | 选中行的下标。支持以下几种情况:<ul><li>若值为 `number` 类型,则表示行所在的数组下标(`0` 开头)</li><li>若值为 `array` 类型 <sup>2.9.1+</sup>,则表示批量下标。</li><li>若值为 `string` 类型,则可设置 `all` 操作全选。</li></ul> | number<br>array<br>string | - |
| checked | 选中状态值。 <ul><li>若传递该属性,则赋值固定值。</li><li>若不传递该属性(默认),则 `checkbox` 将在 `true\|false` 中自动切换值,而 `radio` 将赋值 `true` 固定值。<sup>2.8.4+</sup></li></ul> | boolean | - |
| index | 选中行的下标。支持以下几种情况:<ul><li>若值为 `number` 类型,则表示行所在的数组下标(`0` 开头)</li><li>若值为 `array` 类型 <sup>2.9.1+</sup>,则表示多选下标。</li><li>若值为 `string` 类型,则可设置 `all` 操作全选。</li></ul> | number<br>array<br>string | - |
| checked | 选中状态值。 <ul><li>若传递该属性,则赋值固定值。</li><li>若不传递该属性(默认),则 `checkbox` 将在 `true\|false` 中自动切换值,而 `radio` 将赋值 `true` 固定值。<sup>2.8.4+</sup><br>**注意**:若 `index` 指定为多选或全选,`checked` 应当显式传递固定值</li></ul> | boolean | - |
该方法用于设置行的选中样式及相关的特定属性值 `LAY_CHECKED`

2
examples/table-test.html

@ -84,7 +84,7 @@
(function(off){
if(!off) return;
layui.disuse('table').extend({
table: '{/}https://cdn.staticfile.net/layui/2.7.6/layui.js'
table: '{/}https://cdn.jsdelivr.net/gh/layui/layui@2.7.6/src/modules/table'
});
})();

87
src/modules/table.js

@ -1722,10 +1722,12 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
var options = that.config;
var isCheckAll = opts.index === 'all'; // 是否操作全部
var isCheckMult = layui.type(opts.index) === 'array'; // 是否操作多个
var needDisableTransition= isCheckAll || isCheckMult; // 减少回流
var isCheckAllOrMult = isCheckAll || isCheckMult; // 是否全选或多选
if(needDisableTransition){
that.layBox.addClass(DISABLED_TRANSITION);
// 全选或多选时
if (isCheckAllOrMult) {
that.layBox.addClass(DISABLED_TRANSITION); // 减少回流
if (opts.type === 'radio') return; // radio 不允许全选或多选
}
if(isCheckMult){
@ -1737,13 +1739,14 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
}
// 匹配行元素
var selector = (isCheckAll || isCheckMult) ? 'tr' : 'tr[data-index="'+ opts.index +'"]';
var tbody = that.layBody.children('.layui-table').children('tbody');
var selector = isCheckAllOrMult ? 'tr' : 'tr[data-index="'+ opts.index +'"]';
var tr = function(tr) {
return isCheckAll ? tr : tr.filter(isCheckMult ? function() {
var dataIndex = $(this).data('index');
return opts.index[dataIndex];
} : '[data-index="'+ opts.index +'"]');
}(that.layBody.find(selector));
}(tbody.children(selector));
// 默认属性
opts = $.extend({
@ -1759,61 +1762,46 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
return opts.type === 'radio' ? true : (existChecked ? opts.checked : !value)
};
var ignoreTrIndex = {};
// 设置选中状态
layui.each(thisData, function(i, item){
var radioCheckedIndex;
// 给匹配行设置选中状态
tr.each(function() {
var el = $(this);
var i = el.attr('data-index');
var item = thisData[i];
if (!i) return; // 此时 el 通常为静态表格嵌套时的原始模板
// 绕过空项和禁用项
if(layui.type(item) === 'array' || item[options.disabledName]){
ignoreTrIndex[i] = true;
if (layui.type(item) === 'array' || item[options.disabledName]) {
return;
}
// 匹配条件
var matched = isCheckAll || (
isCheckMult ? opts.index[i] : Number(opts.index) === i
);
// 标记数据选中状态
var checked = item[options.checkName] = getChecked(el.hasClass(ELEM_CHECKED));
// 设置匹配项的选中值
if(matched){
// 标记数据选中状态
var checked = item[options.checkName] = getChecked(item[options.checkName]);
// 标记当前行背景色
// 此处只更新 radio 和 单个 checkbox
if(!isCheckAll && !isCheckMult){
var currTr = tr.filter('[data-index="'+ i +'"]');
currTr[checked ? 'addClass' : 'removeClass'](ELEM_CHECKED);
// 若为 radio 类型,则取消其他行选中背景色
if(opts.type === 'radio'){
currTr.siblings().removeClass(ELEM_CHECKED);
}
}
} else if(opts.type === 'radio') {
delete item[options.checkName];
// 标记当前行背景色
el.toggleClass(ELEM_CHECKED, !!checked);
// 若为 radio 类型,则取消其他行选中背景色
if (opts.type === 'radio') {
radioCheckedIndex = i;
el.siblings().removeClass(ELEM_CHECKED);
}
});
if(isCheckAll){
tr.each(function(i){
var index = this.getAttribute('data-index');
if(!ignoreTrIndex[index]){
var el = $(this);
el.toggleClass(ELEM_CHECKED, !!getChecked(thisData[index][options.checkName]))
}
});
}else if(isCheckMult){
tr.each(function(i){
var index = this.getAttribute('data-index');
if(opts.index[index] && !ignoreTrIndex[index]){
var el = $(this);
el.toggleClass(ELEM_CHECKED, !!getChecked(thisData[index][options.checkName]))
// 若为 radio 类型,移除其他行数据选中状态
if (radioCheckedIndex) {
layui.each(thisData, function(i, item) {
if (Number(radioCheckedIndex) !== Number(i)) {
delete item[options.checkName];
}
});
}
// 若存在复选框或单选框,则标注选中状态样式
var checkedElem = tr.find('input[lay-type="'+ ({
var td = tr.children('td').children('.layui-table-cell');
var checkedElem = td.children('input[lay-type="'+ ({
radio: 'layTableRadio',
checkbox: 'layTableCheckbox'
}[opts.type] || 'checkbox') +'"]:not(:disabled)');
@ -1826,7 +1814,7 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
that.syncCheckAll();
if(needDisableTransition){
if(isCheckAllOrMult){
setTimeout(function(){
that.layBox.removeClass(DISABLED_TRANSITION);
},100)
@ -2438,9 +2426,10 @@ layui.define(['lay', 'laytpl', 'laypage', 'form', 'util'], function(exports){
index: index,
checked: checked
});
layui.stope(e);
}
layui.stope(e);
// 事件
layui.event.call(
checkbox[0],

Loading…
Cancel
Save