表头筛选问题总结

  1. 表头筛选组件中的el-tree数据过多,导致生成的DOM节点过多,引起客户端性能问题。

    HeaderFilter_2020-12-31_09-51-20

  2. 数据过多时全选反选失去意义。

    HeaderFilter01_2020-12-31_09-53-08

  3. 经本机测试,当数据超过1000条时,关键字搜索会有明显的延迟,大部分客户的客户端性能都无法达到本机的水平。下图搜索腾讯,页面将有2秒以上的延迟。

    HeaderFilter03_2020-12-31_10-48-08

优化目标

  1. 表头筛选组件实现秒开,反应速度应在50ms以下。
  2. 全选反选功能只提供给静态数据。
  3. 数据筛选时,本地检索实现实时反馈。

技术与实施方案

  1. 所有请求返回的数据采用分页请求,不再加载所有数据,数据量不超过100

    listOnly=1&listRows=100
    
  2. 区分静态数据和动态获取,动态获取的数据无法使用全选与反选,动态数据检索采用分页请求接口的形式,每页数据量为20条,可上下翻页,可全选本页,为防止已选选项丢失,动态分页获取的数据提供一个已选的可视化tree组件,可在已选的tree中实现清空等交互功能。

    <div>已选</div>
    <el-tree
      :data='selectedData'
      v-if='selectedData.length > 0'
      ...
      >
    </el-tree>
    

    HeaderFilter02_2020-12-31_10-23-37

  3. 严格区分动态加载资源和静态资源,当数据量大于500时,采用接口获取方式,随数据量减少,本地检索基本能实现实时反馈。

  4. 所有表头筛选组件需DOM渲染完成后才请求接口,避免阻塞UI渲染,造成不好的体验:

    // 挂载之后请求
    mounted() {
      this.$axiosGet({...});
    }
    

具体实现细节

表头筛选优化任务拆分_2021-01-06_15-04-16

  1. 删除弃用功能代码。

  2. 更新用户界面。

    Filter_2021-01-08_11-18-43

    • 取消待选取的复选框。

    • 调整组件大小,提供更大的可操作范围,宽度从默认的150px提高到375pxUI组件的size统一改为small

      Filter_2021-01-08_11-21-39

    • 取消之前代码中的全选反选功能,新增分页、全选本页等功能。

      filter

  3. 使用mockjs模拟返回数据。

    • 安装mockjs——npm i mockjs --save-dev

    • 拦截customer接口,返回模拟数据提供测试,可分页,可搜索。

      // 引入mockjs
      import Mock from 'mockjs';
      import mockApi from './mockApi';
      const Random = Mock.Random;
      const { customer_list_only } = mockApi;
      Random.id();
      Random.cname();
      Mock.mock(customer_list_only.url, customer_list_only.type, customer_list_only.template);
      
      // 配置返回模板
      {customer_list_only: { url: /\/api\/customers\?listOnly=\d&listRows=\d*/, type: 'get', template: { "data": { "data|10": [{ "id": "@id", "name": "@cname()" }], "total": 40, "per_page": 10, "current_page": 1, "last_page": 4, }, "status": 1, "info": "获取客户数据成功" } },}
      
  4. 具体的功能逻辑处理。

    • remote_select类型改为分页请求,请求逻辑不再放在vuex中实现,数据同样不再放在vuex中。

      // 旧版
      computed: {
        cacheData() {}
      }
      // 新版
      data() {
        return {
          treeData: [],
        }
      },
      methods: {
        initData() {
          // ...
          this.treeData = data;
        },
      },
      
    • 全选本页逻辑:

      treeData.forEach(t => {
        // 本页中已选的不用重复添加
        const b = this.selected.some(s => s.id === t.id)
        if(!b) { /* 加入已选 */ }
      })
      
  5. 修改请求参数。

    vuex中的筛选参数以及路由参数放在initData方法的请求中。

  6. 可选区域需有选中状态体现

    • 选中区域取消时,可选区域的选中状态取消。

    • 翻页时,需将可选区域中已选中的全都体现出选中状态。

      watch: {
        selectedData(v){
          // 改变已选区域中已选选项的样式
        }
      }
      
    • 已选区域的滚动条必须保持在最新加入的位置。

配置项整理

名称 用途 取值范围 是否需要
type 配置项类型 textdateremote_selectstatic_select
id 与表格的配置项prop值匹配的字段 application_date等文本
name 显示在表格上的字段中文名称 案号等文本
map_type hashmapselectConfig中对应的选项字段名称 user_internal等文本 -
url 服务器获取筛选数据时,提供的接口地址 true或者/applicants等接口 -
data_key 接口返回的数据中选项对应的属性值 data等文本 -
sortable 是否需要排序 truefalse -
skip 跳过哪些范围选项的id id数组,如[1, 3] -
isRadio 是否是单选 truefalse -
isNoShowTextFilterRelate 是否显示筛选范围 truefalse -
validationFunc 筛选数据的验证方法 function,有两个参数,第一个为所选的数据,第二个为配置的err_msg -
err_msg 数据错误时显示的信息 请选择连续的月份!等文本 -
oneSelect 是否是单选 truefalse -
  1. 其中isRadiooneSelect为重复配置。
  2. isNoShowTextFilterRelate能使用skip.length代替。
  3. url的配置分为两种情况:
    • type=remote_select时,值为string类型的api接口。
    • type=static_select时,值为true或者undefined;当值为true时,使用的是通过vuex中的方法initializeSelectorCache获取的数据;当值为undefined时,为selectConfig中配置的静态选项或者保存在vuex中的数据。

配置项类型整理

类型 名称 用途
text 文本 关键字为文本类型的搜索
date 日期 关键字为日期类型的搜索
remote_select 筛选项远程搜索(接口返回) 数据源为接口请求的数据
static_select 筛选项本地数据搜索 数据源为hashmap中的数据,或者selectConfig.js中的数据

现有问题

  1. 一次性获取的接口并没有翻页的数据,需要整理出来全部修改(大部分是type=static_select类型的)。
  2. remote_select类型的全部需要修改接口,加上可表明是哪个列表需要的数据。
  3. 重新打开表头筛选组件是否要重新刷新数据,刷新与不刷新分别带来的问题为:
    • 刷新:勾选项是否跟着刷新,勾选项刷新了就与已经在查询条件中的筛选项参数差异了。
    • 不刷新:如果后面点了其它字段的表头筛选,则会导致选项不准确。

测试用例

用例名称 操作步骤 预期结果
打开表头筛选 打开带有表头筛选的页面->点击表头的倒三角按钮 1.表头筛选组件被打开;2.加载筛选数据。
点击筛选项并筛选 同“打开表头筛选”->点选待选的选项->点击确定按钮 1.被选选项加入到已选区域;2.待选区域已选择的选项背景色加深;3.可选数量加1;4.已选区域的数据作为筛选条件查询列表。
点击全选本页并筛选 同“打开表头筛选”->点击全选本页->点击确定按钮 1.待选区域的所有选项加入到已选区域;2.待选区域的所有选项背景色加深;3.可选数量加20;4.同上4;5.已选区域滚动条保持在最底端。
取消已选条件并筛选 同“打开表头筛选”->点击多个待选选项->在已选中取消一个或多个选项->点击确定按钮 同“点击筛选项并筛选”1、2;3.取消的选项在已选区域中消失,待选区中取消的选项背景颜色恢复正常底色;4.剩余选项作为筛选条件作为筛选条件查询列表。
翻页选择筛选条件 同“打开表头筛选”->当前页选择几个选项或者全选之后点击“下页”,在第二页选择几个或者全选之后点击“上页”或者“下页”继续选择->点击确定按钮 同“点击筛选项并筛选”1、2;3.发送请求第二页的数据并显示在待选区域;4.翻回上页时,已选数据依然为深色底色。5.同上5。
搜索选择筛选条件 同“打开表头筛选”->在搜索框中输入关键字->选择筛选结果->点击确定按钮 同“点击筛选项并筛选”1、2;3.返回关键字搜索结果;4.同“点击筛选项并筛选”

测试覆盖

headerFilterConfig中不同配置类型需独立测试一遍。

git分支

feature_header_filter_performance

其它优化

筛选数据要求只包含列表中有的数据

此需求需要将所有提供筛选的数据都使用接口返回,修改所有配置文件有关人员的接口,请求中携带的参数必须包含当前列表的所有查询条件,例如:

// 获取专利列表中的所有客户
url = 'api/patent/customer?xxx=xxx&xxx=xxx';

使用vuex实现的数据缓存功能的initializeSelectorCache方法将无法满足需求,数据请求将放在组件中实现。

高级筛取值范围选项

与表头筛选类似,高级筛选随着筛选内容不同,其也应有取值范围选择:

Filter01_2020-12-31_11-32-10

Filter02_2020-12-31_11-35-38

专利、商标、版权详情

ChromePerformance工具中可以看到,造成延迟的很大一部分原因是使用了lodash的防抖方法:

组件问题_2020-12-21_16-18-33

之前使用防抖方法是为了防止用户频繁高速点击行数据,在解决JumpSelect请求数的问题之后,可将防抖时间减少到100~200之间,可以明显体验到速度提升上来,用户第一次点击时,也不应经过防抖方法。

版本管理

由于稳定版本计划周期较日常维护太长,需要保证performance分支不落后于主分支,当天如果有发布,则必须同步到performance分支。


工作     

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

使用browser-sync同步文章修改 上一篇
刷题笔记02 下一篇