表头筛选问题总结
表头筛选组件中的
el-tree数据过多,导致生成的DOM节点过多,引起客户端性能问题。
数据过多时全选反选失去意义。

经本机测试,当数据超过
1000条时,关键字搜索会有明显的延迟,大部分客户的客户端性能都无法达到本机的水平。下图搜索腾讯,页面将有2秒以上的延迟。
优化目标
- 表头筛选组件实现秒开,反应速度应在50ms以下。
- 全选反选功能只提供给静态数据。
- 数据筛选时,本地检索实现实时反馈。
技术与实施方案
所有请求返回的数据采用分页请求,不再加载所有数据,数据量不超过
100:listOnly=1&listRows=100区分静态数据和动态获取,动态获取的数据无法使用全选与反选,动态数据检索采用分页请求接口的形式,每页数据量为
20条,可上下翻页,可全选本页,为防止已选选项丢失,动态分页获取的数据提供一个已选的可视化tree组件,可在已选的tree中实现清空等交互功能。<div>已选</div> <el-tree :data='selectedData' v-if='selectedData.length > 0' ... > </el-tree>
严格区分动态加载资源和静态资源,当数据量大于
500时,采用接口获取方式,随数据量减少,本地检索基本能实现实时反馈。所有表头筛选组件需
DOM渲染完成后才请求接口,避免阻塞UI渲染,造成不好的体验:// 挂载之后请求 mounted() { this.$axiosGet({...}); }
具体实现细节

删除弃用功能代码。
更新用户界面。

取消待选取的复选框。
调整组件大小,提供更大的可操作范围,宽度从默认的
150px提高到375px,UI组件的size统一改为small。
取消之前代码中的全选反选功能,新增分页、全选本页等功能。

使用
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": "获取客户数据成功" } },}
具体的功能逻辑处理。
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) { /* 加入已选 */ } })
修改请求参数。
将
vuex中的筛选参数以及路由参数放在initData方法的请求中。可选区域需有选中状态体现。
选中区域取消时,可选区域的选中状态取消。
翻页时,需将可选区域中已选中的全都体现出选中状态。
watch: { selectedData(v){ // 改变已选区域中已选选项的样式 } }已选区域的滚动条必须保持在最新加入的位置。
配置项整理
| 名称 | 用途 | 取值范围 | 是否需要 |
|---|---|---|---|
| type | 配置项类型 | text、date、remote_select、static_select |
√ |
| id | 与表格的配置项prop值匹配的字段 |
如application_date等文本 |
√ |
| name | 显示在表格上的字段中文名称 | 如案号等文本 |
√ |
| map_type | hashmap与selectConfig中对应的选项字段名称 |
如user_internal等文本 |
- |
| url | 服务器获取筛选数据时,提供的接口地址 | 为true或者/applicants等接口 |
- |
| data_key | 接口返回的数据中选项对应的属性值 | 如data等文本 |
- |
| sortable | 是否需要排序 | true、false |
- |
| skip | 跳过哪些范围选项的id |
id数组,如[1, 3] |
- |
| isRadio | 是否是单选 | true、false |
- |
| isNoShowTextFilterRelate | 是否显示筛选范围 | true、false |
- |
| validationFunc | 筛选数据的验证方法 | function,有两个参数,第一个为所选的数据,第二个为配置的err_msg |
- |
| err_msg | 数据错误时显示的信息 | 如请选择连续的月份!等文本 |
- |
| oneSelect | 是否是单选 | true、false |
- |
- 其中
isRadio与oneSelect为重复配置。 isNoShowTextFilterRelate能使用skip.length代替。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中的数据 |
现有问题
- 一次性获取的接口并没有翻页的数据,需要整理出来全部修改(大部分是
type=static_select类型的)。 remote_select类型的全部需要修改接口,加上可表明是哪个列表需要的数据。- 重新打开表头筛选组件是否要重新刷新数据,刷新与不刷新分别带来的问题为:
- 刷新:勾选项是否跟着刷新,勾选项刷新了就与已经在查询条件中的筛选项参数差异了。
- 不刷新:如果后面点了其它字段的表头筛选,则会导致选项不准确。
测试用例
| 用例名称 | 操作步骤 | 预期结果 |
|---|---|---|
| 打开表头筛选 | 打开带有表头筛选的页面->点击表头的倒三角按钮 | 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方法将无法满足需求,数据请求将放在组件中实现。
高级筛取值范围选项
与表头筛选类似,高级筛选随着筛选内容不同,其也应有取值范围选择:


专利、商标、版权详情
在Chrome的Performance工具中可以看到,造成延迟的很大一部分原因是使用了lodash的防抖方法:

之前使用防抖方法是为了防止用户频繁高速点击行数据,在解决JumpSelect请求数的问题之后,可将防抖时间减少到100~200之间,可以明显体验到速度提升上来,用户第一次点击时,也不应经过防抖方法。
版本管理
由于稳定版本计划周期较日常维护太长,需要保证performance分支不落后于主分支,当天如果有发布,则必须同步到performance分支。