Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(treeTable): 修复重载数据时,指定参数 scrollPos: 'fixed' 无效的问题 #1892

Merged
merged 8 commits into from
May 17, 2024

Conversation

jichuanan
Copy link
Contributor

@jichuanan jichuanan commented May 12, 2024

😃 本次 PR 的变化性质

请至少勾选一项

  • 功能新增
  • 问题修复
  • 功能优化
  • 分支合并
  • 其他改动:请在此处填写

🌱 本次 PR 的变化内容

✅ 本次 PR 的满足条件

请在申请合并之前,将符合条件的每一项进行勾选

  • [x ] 已提供在线演示地址(如:codepen, stackblitz)或无需演示
  • 已对每一项的改动均测试通过
  • 已提供具体的变化内容说明

Review PR in StackBlitz Submitted with StackBlitz.

无法实现保持滚动条在原有位置的问题。
Copy link

stackblitz bot commented May 12, 2024

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@sentsim sentsim requested a review from Sight-wcg May 13, 2024 08:27
@sentsim sentsim changed the title 修正treeTable重载数据时,指定参数 scrollPos: 'fixed' 无效的问题 fix(treeTable): 修复重载数据时,指定参数 scrollPos: 'fixed' 无效的问题 May 13, 2024
@sentsim sentsim self-requested a review May 13, 2024 08:28
sentsim

This comment was marked as outdated.

src/modules/treeTable.js Outdated Show resolved Hide resolved
src/modules/treeTable.js Outdated Show resolved Hide resolved
src/modules/treeTable.js Outdated Show resolved Hide resolved
src/modules/treeTable.js Outdated Show resolved Hide resolved
src/modules/treeTable.js Outdated Show resolved Hide resolved
@Sight-wcg

This comment has been minimized.

jichuanan and others added 5 commits May 14, 2024 15:06
Co-authored-by: morning-star <26325820+Sight-wcg@users.noreply.github.com>
Co-authored-by: morning-star <26325820+Sight-wcg@users.noreply.github.com>
主要修改点:
1,通过给done包装函数设置scrollPosPatch标志位,避免重复包装;
2,包装后的done函数执行完毕后,恢复原来的done函数,避免以后再次触发done函数时,仍然执行保持滚动条位置的逻辑;
1. 将修复代码迁移至 updateOptions
2. table done 回调第四个参数,现在可以区分 reloadData 和 renderData
@jichuanan
Copy link
Contributor Author

另外发现 table 选项 scrollPos: 'fixed' 和文档有些许出入,有劳 @sentsim 确认一下。 实测发现 2.7.3+ 分页切换时,无法固定滚动条位置。https://stackblitz.com/edit/8mjklk?file=index.html

image

如果切换分页无法固定滚动条是 BUG,那就只能在 table.js 中修复 #1891,采用 “afterDone” 的方式修复。

应该是我理解错了,编辑。

指定scrollPos: 'fixed'选项,table分页切换时,确实无法固定滚动条,会跳到顶部,因为切换分页时,opts.type的值不是'reloadData',固定滚动条位置只对reloadData有效。

      // 容器的滚动条位置
      if(!(options.scrollPos === 'fixed' && opts.type === 'reloadData')){
        that.layBody.scrollTop(0);
      }

如果想在table切换分页时,也能固定滚动条,可以修改分页时的事件函数jump中调用pullData函数时,指定type为reloadData,可以修正这个问题(不确定会不会引起其他问题。。。)

        jump: function(obj, first){
          if(!first){
            //分页本身并非需要做以下更新,下面参数的同步,主要是因为其它处理统一用到了它们
            //而并非用的是 options.page 中的参数(以确保分页未开启的情况仍能正常使用)
            that.page = obj.curr; //更新页码
            options.limit = obj.limit; //更新每页条数

            that.pullData(obj.curr, {
              type: "reloadData"
            });
          }
        }

@Sight-wcg
Copy link
Collaborator

Sight-wcg commented May 15, 2024

另外发现 table 选项 scrollPos: 'fixed' 和文档有些许出入,有劳 @sentsim 确认一下。 实测发现 2.7.3+ 分页切换时,无法固定滚动条位置。https://stackblitz.com/edit/8mjklk?file=index.html

image

如果切换分页无法固定滚动条是 BUG,那就只能在 table.js 中修复 #1891,采用 “afterDone” 的方式修复。

应该是我理解错了,编辑。

指定scrollPos: 'fixed'选项,table分页切换时,确实无法固定滚动条,会跳到顶部,因为切换分页时,opts.type的值不是'reloadData',固定滚动条位置只对reloadData有效。

      // 容器的滚动条位置
      if(!(options.scrollPos === 'fixed' && opts.type === 'reloadData')){
        that.layBody.scrollTop(0);
      }

如果想在table切换分页时,也能固定滚动条,可以修改分页时的事件函数jump中调用pullData函数时,指定type为reloadData,可以修正这个问题(不确定会不会引起其他问题。。。)

        jump: function(obj, first){
          if(!first){
            //分页本身并非需要做以下更新,下面参数的同步,主要是因为其它处理统一用到了它们
            //而并非用的是 options.page 中的参数(以确保分页未开启的情况仍能正常使用)
            that.page = obj.curr; //更新页码
            options.limit = obj.limit; //更新每页条数

            that.pullData(obj.curr, {
              type: "reloadData"
            });
          }
        }

是的,在这个 PR 之后,很容易支持分页切换时仍保持滚动条位置。调试了一遍,应该没问题,分页切换加载数据和 reloadData
行为一致。
这一块应该就是这么设计的,分页切换时滚动条始终置顶,也符合大多数场景的需求。

@jichuanan
Copy link
Contributor Author

还想到一种修改办法,只修改table.js就可以了。
引起scrollPos对treeTable无效的原因是,treeTable在reloadData时,先只显示顶层节点,然后根据重载数据前保存的子节点展开状态,重新展开需要展开的子节点。这样在顶层节点显示后,子节点展开前,顶层节点比较少的情况下,滚动条就消失了。当子节点展开后,重新显示的滚动条是在顶部的。
所以按照这个思路,可以在reloadData重新绘制table内容时,先固定死原来table内容的高度为更新前的高度,等更新完成后,在done函数里面,重新把table内容的高度设置为auto,这样就可以利用浏览器的特性实现自然实现固定滚动条的需求。

table和treeTable的代码太复杂了,超越了一个java程序员的能力范围了,只能提供示例代码供参考。
在table的 Class.prototype.renderData 函数中添加如下代码(简单测试有效,但不确定会带来什么其他问题):

      // 容器的滚动条位置
      if(!(options.scrollPos === 'fixed' && opts.type === 'reloadData')){
        that.layBody.scrollTop(0);
      }
      if(options.scrollPos === 'reset'){
        that.layBody.scrollLeft(0);
      }

     // 添加代码开始 ******************************************************
      // 定义render方法自己的done包装函数,在talbe的done里面做一些最后需要处理的事情
      var done = options.done;
      if (!options.done || !options.done.renderDataMod) {
        options.done = function() {
          var args = arguments;
          var doneThat = this;
          var type = args[3];
          if (layui.type(done) === 'function') {
            return done.apply(doneThat, args);
          }
          if (doneThat.scrollPos === 'fixed' && type === 'reloadData') {
            // 去掉table在renderData时为了保持高度而设置的height属性
            that.elem.find(ELEM_BODY).children('table').css('height', 'auto');
          }
        }
        options.done.renderDataMod = true;
      }

      // 为了实现 scrollPos: 'fixed' ,更新table内容前,先固定住table的高度为更新前的高度,
      // 这样可以避免在某些案例下因为滚动条消失而后有重新显示时,滚动条位置丢失的问题
      if (options.scrollPos === 'fixed' && opts.type === 'reloadData') {
        var tableBodys = that.elem.find(ELEM_BODY).children('table');
        var mainTableHeight = tableBodys.height();
        tableBodys.css("height", mainTableHeight);
      }
     // 添加代码结束 ******************************************************

      that.layMain.find('.'+ NONE).remove();
      that.layMain.find('tbody').html(trs.join(''));
      that.layFixLeft.find('tbody').html(trs_fixed.join(''));
      that.layFixRight.find('tbody').html(trs_fixed_r.join(''));

@Sight-wcg
Copy link
Collaborator

Sight-wcg commented May 15, 2024

还想到一种修改办法,只修改table.js就可以了。
引起scrollPos对treeTable无效的原因是,treeTable在reloadData时,先只显示顶层节点,然后根据重载数据前保存的子节点展开状态,重新展开需要展开的子节点。这样在顶层节点显示后,子节点展开前,顶层节点比较少的情况下,滚动条就消失了。当子节点展开后,重新显示的滚动条是在顶部的。
所以按照这个思路,可以在reloadData重新绘制table内容时,先固定死原来table内容的高度为更新前的高度,等更新完成后,在done函数里面,重新把table内容的高度设置为auto,这样就可以利用浏览器的特性实现自然实现固定滚动条的需求。

table和treeTable的代码太复杂了,超越了一个java程序员的能力范围了,只能提供示例代码供参考。
在table的 Class.prototype.renderData 函数中添加如下代码(简单测试有效,但不确定会带来什么其他问题):

      // 容器的滚动条位置
      if(!(options.scrollPos === 'fixed' && opts.type === 'reloadData')){
        that.layBody.scrollTop(0);
      }
      if(options.scrollPos === 'reset'){
        that.layBody.scrollLeft(0);
      }

     // 添加代码开始 ******************************************************
      // 定义render方法自己的done包装函数,在talbe的done里面做一些最后需要处理的事情
      var done = options.done;
      if (!options.done || !options.done.renderDataMod) {
        options.done = function() {
          var args = arguments;
          var doneThat = this;
          var type = args[3];
          if (layui.type(done) === 'function') {
            return done.apply(doneThat, args);
          }
          if (doneThat.scrollPos === 'fixed' && type === 'reloadData') {
            // 去掉table在renderData时为了保持高度而设置的height属性
            that.elem.find(ELEM_BODY).children('table').css('height', 'auto');
          }
        }
        options.done.renderDataMod = true;
      }

      // 为了实现 scrollPos: 'fixed' ,更新table内容前,先固定住table的高度为更新前的高度,
      // 这样可以避免在某些案例下因为滚动条消失而后有重新显示时,滚动条位置丢失的问题
      if (options.scrollPos === 'fixed' && opts.type === 'reloadData') {
        var tableBodys = that.elem.find(ELEM_BODY).children('table');
        var mainTableHeight = tableBodys.height();
        tableBodys.css("height", mainTableHeight);
      }
     // 添加代码结束 ******************************************************

      that.layMain.find('.'+ NONE).remove();
      that.layMain.find('tbody').html(trs.join(''));
      that.layFixLeft.find('tbody').html(trs_fixed.join(''));
      that.layFixRight.find('tbody').html(trs_fixed_r.join(''));

这也是一个很好的解决方案,同时能避免更新数据时 table 视图闪烁,有固定列时效果会明显一些。

@sentsim
Copy link
Member

sentsim commented May 15, 2024

是的,在这个 PR 之后,很容易支持分页切换时仍保持滚动条位置。调试了一遍,应该没问题,分页切换加载数据和 reloadData 行为一致。 这一块应该就是这么设计的,分页切换时滚动条始终置顶,也符合大多数场景的需求。

没错,当 scrollPos: 'fixed' 时,主要是对执行“数据重载”时的滚动条位置保持,而非针对分页,所以文档对该值的应用场景也特别进行了注明。该选项值之所以不对分页动作做支持,是因为翻页时的纵向滚动条置顶符合正常的操作习惯,@Sight-wcg 上述理解完全正确。
image

注意到晨星将相关代码迁移到了 updateOptions 方法中,减少了 @jichuanan 童鞋之前重写 options.done 的冗余,赞!
@jichuanan 提供该问题的两种解决思路都很好,对问题深剖的态度值得学习,期待 Layui 有更多社区的力量接力。

PS: 我在 #1678 回复的“该问题暂时无解”欠缺考虑,也不符合精雕细琢的工匠精神,在这里表示惭愧一下 ~

@sentsim sentsim added the wonderful 精彩的议题或讨论 label May 15, 2024
@Cuixq123
Copy link

看的津津有味,没想到还是个java大佬

@Cuixq123
Copy link

大佬们 着急用这个改动,这个改动在layui.js 里面加在哪啊

@jichuanan
Copy link
Contributor Author

大佬们 着急用这个改动,这个改动在layui.js 里面加在哪啊

在这个问题修正前,先在自己业务代码里面打个补丁将就着用一下吧

https://stackblitz.com/edit/3mynts-8efyex?file=index.html

  // 表头工具栏工具事件
  treeTable.on("toolbar(ID-treeTable-demo)", function (obj) {
    var config = obj.config;
    var tableId = config.id;
    // 重载数据
    if (obj.event === "reloadData") {
      // 修正treeTable的 scrollPos: 'fixed' 参数无效,重载数据不能保持滚动条位置的问题
      let scrollTop = $('div[lay-id="' + tableId + '"]').find('.layui-table-body.layui-table-main').scrollTop();
      treeTable.reloadData('ID-treeTable-demo', {
        scrollPos: 'fixed',
        done: function() {
          $('div[lay-id="' + tableId + '"]').find('.layui-table-body').scrollTop(scrollTop);
        }
      });
    }
  });

Copy link
Member

@sentsim sentsim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

本地测试一切正常。

@sentsim sentsim merged commit 627dc8b into layui:main May 17, 2024
@jichuanan jichuanan deleted the jichuanan/issue1891 branch May 22, 2024 01:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wonderful 精彩的议题或讨论
Projects
None yet
Development

Successfully merging this pull request may close these issues.

treeTable节点展开时,显示的滚动条设置通过设置scrollPos: 'fixed'无法保持
4 participants