mirror of https://github.com/layui/layui
fix(table): 修复自动行高时固定列高度异常 (#2825)
* fix(select): select 面板大小变化时重新定位 * update * fix(table): 修复自动行高时固定列高度异常 * feat(table): 新增 syncFixedRowHeight 选项 * update * update * update * update * update * fix: 重复 render 时停止 onserveResize * update * docs: 更新 table 文档 * fix: 修复一些边缘情况 * fix: 修复边缘情况main
parent
182c0bcedd
commit
1ec6c91da6
|
@ -254,6 +254,17 @@ height: function(){
|
|||
|
||||
</td>
|
||||
<td>string</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>syncFixedRowHeight <sup>2.12+ 实验性</sup></td>
|
||||
<td>
|
||||
|
||||
是否强制计算表格主区域的行高度并同步到固定列区域。开启后会对表格性能有一定的影响,仅适用于行高度自适应的场景。
|
||||
该功能使用 [ResizeObserver](https://developer.mozilla.org/zh-CN/docs/Web/API/ResizeObserver) 实现,如果你的浏览器不支持 `ResizeObserver`,可以尝试添加 [polyfill](https://github.com/que-etc/resize-observer-polyfill) 来解决兼容性问题。
|
||||
|
||||
</td>
|
||||
<td>boolean</td>
|
||||
<td>-</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
@ -151,9 +151,12 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
var ELEM_TOOL_PANEL = 'layui-table-tool-panel';
|
||||
var ELEM_EXPAND = 'layui-table-expanded';
|
||||
var DISABLED_TRANSITION = 'layui-table-disabled-transition';
|
||||
var FIXED_HEIGHT_PATCH = 'layui-table-fixed-height-patch';
|
||||
|
||||
var DATA_MOVE_NAME = 'LAY_TABLE_MOVE_DICT';
|
||||
|
||||
var resizeObserver = lay._createResizeObserver(MOD_NAME);
|
||||
|
||||
// thead 区域模板
|
||||
var TPL_HEADER = function(options){
|
||||
var rowCols = '{{#var colspan = layui.type(item2.colspan2) === \'number\' ? item2.colspan2 : item2.colspan; if(colspan){}} colspan="{{=colspan}}"{{#} if(item2.rowspan){}} rowspan="{{=item2.rowspan}}"{{#}}}';
|
||||
|
@ -288,6 +291,7 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
var that = this;
|
||||
that.index = ++table.index;
|
||||
that.config = $.extend({}, that.config, table.config, options);
|
||||
that.unobserveResize = $.noop;
|
||||
that.render();
|
||||
};
|
||||
|
||||
|
@ -318,6 +322,11 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
options.elem.attr('id') || that.index
|
||||
);
|
||||
|
||||
// 重复 render 时清理旧实例
|
||||
if(thisTable.that[id] && thisTable.that[id] !== that){
|
||||
thisTable.that[id].dispose();
|
||||
}
|
||||
|
||||
thisTable.that[id] = that; // 记录当前实例对象
|
||||
thisTable.config[id] = options; // 记录当前实例配置项
|
||||
|
||||
|
@ -460,6 +469,7 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
|
||||
that.pullData(that.page); // 请求数据
|
||||
that.events(); // 事件
|
||||
that.observeResize(); // 观察尺寸变化
|
||||
};
|
||||
|
||||
// 根据列类型,定制化参数
|
||||
|
@ -622,6 +632,7 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
|
||||
// 自定义 css 属性
|
||||
if (options.css) text.push(options.css);
|
||||
text.push('.' + FIXED_HEIGHT_PATCH + '{height:auto;}');
|
||||
|
||||
// 生成 style
|
||||
lay.style({
|
||||
|
@ -1521,6 +1532,11 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
}, 50);
|
||||
that.haveInit = true;
|
||||
|
||||
// reloadData 或 renderData 时,tbody 高度可能不变,需要主动同步
|
||||
if(that.needSyncFixedRowHeight){
|
||||
that.calcFixedRowHeight();
|
||||
}
|
||||
|
||||
layer.close(that.tipsIndex);
|
||||
};
|
||||
|
||||
|
@ -2530,12 +2546,20 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
var othis = $(this);
|
||||
var index = othis.index();
|
||||
if(othis.data('off')) return; // 不触发事件
|
||||
that.layBody.find('tr:eq('+ index +')').addClass(ELEM_HOVER)
|
||||
var trsElem = that.layBody.find('tr:eq('+ index +')');
|
||||
trsElem.addClass(ELEM_HOVER);
|
||||
if(that.needSyncFixedRowHeight){
|
||||
that.fixedRowHeightPatchOnHover(this, trsElem, true);
|
||||
}
|
||||
}).on('mouseleave', 'tr', function(){ // 鼠标移出行
|
||||
var othis = $(this);
|
||||
var index = othis.index();
|
||||
if(othis.data('off')) return; // 不触发事件
|
||||
that.layBody.find('tr:eq('+ index +')').removeClass(ELEM_HOVER)
|
||||
var trsElem = that.layBody.find('tr:eq('+ index +')');
|
||||
trsElem.removeClass(ELEM_HOVER);
|
||||
if(that.needSyncFixedRowHeight){
|
||||
that.fixedRowHeightPatchOnHover(this, trsElem, false);
|
||||
}
|
||||
}).on('click', 'tr', function(e){ // 单击行
|
||||
setRowEvent.call(this, 'row', e);
|
||||
}).on('dblclick', 'tr', function(e){ // 双击行
|
||||
|
@ -2922,6 +2946,119 @@ layui.define(['lay', 'i18n', 'laytpl', 'laypage', 'form', 'util'], function(expo
|
|||
}
|
||||
};
|
||||
|
||||
Class.prototype.dispose = function(){
|
||||
var that = this;
|
||||
|
||||
that.unobserveResize();
|
||||
for (const propName in that) {
|
||||
if(lay.hasOwn(that, propName) && propName !== 'config'){
|
||||
that[propName] = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Class.prototype.calcFixedRowHeight = function(){
|
||||
var that = this;
|
||||
|
||||
var tableElem = that.layMain.children('table');
|
||||
var leftTrs = that.layFixLeft.find('>.layui-table-body>table>tbody>tr');
|
||||
var rightTrs = that.layFixRight.find('>.layui-table-body>table>tbody>tr');
|
||||
var mainTrs = tableElem.find('>tbody>tr');
|
||||
|
||||
// 批量获取主表格行高,设置高度以优化性能
|
||||
var heights = [];
|
||||
mainTrs.each(function() {
|
||||
heights.push(that.getElementSize(this).height);
|
||||
});
|
||||
|
||||
if (leftTrs.length) {
|
||||
leftTrs.each(function(i) {
|
||||
if (heights[i]) {
|
||||
this.style.height = heights[i] + 'px';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (rightTrs.length) {
|
||||
rightTrs.each(function(i) {
|
||||
if (heights[i]) {
|
||||
this.style.height = heights[i] + 'px';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 鼠标悬停于某一列纵向移动时,若单元格会出现横向滚动条,此时 tbody 高度不变,需要修复行高
|
||||
Class.prototype.fixedRowHeightPatchOnHover = function (targetEl, trsElem, isEnter) {
|
||||
var that = this;
|
||||
var style = that.elem.children('style')[0];
|
||||
var selector = '.' + FIXED_HEIGHT_PATCH;
|
||||
|
||||
trsElem.toggleClass(FIXED_HEIGHT_PATCH, isEnter);
|
||||
// 将当前鼠标悬停行的高度同步到 FIXED_HEIGHT_PATCH (所有区域)类名的样式中
|
||||
if (isEnter) {
|
||||
lay.getStyleRules(style, function (item) {
|
||||
if (item.selectorText === selector) {
|
||||
item.style.setProperty('height', that.getElementSize(targetEl).height + 'px', 'important');
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// 将当前鼠标悬停行主区域的行高同步到固定列行
|
||||
var height;
|
||||
lay.getStyleRules(style, function (item) {
|
||||
if (item.selectorText === selector) {
|
||||
item.style.setProperty('height', 'auto');
|
||||
}
|
||||
})
|
||||
trsElem = trsElem.filter(function () {
|
||||
var tr = $(this);
|
||||
var isFixed = tr.closest(ELEM_FIXED, that.layBox).length > 0;
|
||||
if (!isFixed) {
|
||||
height = that.getElementSize(tr[0]).height;
|
||||
}
|
||||
return isFixed;
|
||||
})
|
||||
|
||||
trsElem.css('height', height);
|
||||
}
|
||||
}
|
||||
|
||||
Class.prototype.observeResize = function(){
|
||||
var that = this;
|
||||
|
||||
if(!resizeObserver) return;
|
||||
|
||||
that.unobserveResize();
|
||||
|
||||
var el = that.elem[0];
|
||||
var tableEl = that.layMain.children('table')[0];
|
||||
// 显示或隐藏时重置列宽
|
||||
resizeObserver.observe(el, $.proxy(that.resize, that));
|
||||
|
||||
// 同步固定列表格和主表格高度
|
||||
var lineStyle = that.config.lineStyle;
|
||||
var isAutoHeight = lineStyle && /\bheight\s*:\s*auto\b/g.test(lineStyle);
|
||||
// 只重载数据时需要主动同步高度,因为 tbody 大小可能不变
|
||||
var needSyncFixedRowHeight = that.needSyncFixedRowHeight = (that.layBody.length > 1) && (that.config.syncFixedRowHeight || (that.config.syncFixedRowHeight !== false && isAutoHeight));
|
||||
|
||||
if(needSyncFixedRowHeight){
|
||||
resizeObserver.observe(
|
||||
tableEl,
|
||||
$.proxy(that.calcFixedRowHeight, that)
|
||||
);
|
||||
}
|
||||
|
||||
that.unobserveResize = function(){
|
||||
resizeObserver.unobserve(el);
|
||||
if(needSyncFixedRowHeight){
|
||||
resizeObserver.unobserve(tableEl);
|
||||
}
|
||||
|
||||
that.unobserveResize = $.noop;
|
||||
}
|
||||
};
|
||||
|
||||
// 全局事件
|
||||
(function(){
|
||||
// 自适应尺寸
|
||||
|
|
Loading…
Reference in New Issue