巧用order实现列表排序
前言
近些年,随着 web 应用的蓬勃发展,前端所需要承载的业务需求与开发任务越来越多。一些曾经第一反应是 “调一下后端接口就完事儿” 的任务,随着 数据量 的提升以及对 用户体验 的追求的提高,问题变的没有那么简单了。今天我们来讨论一下 “如何在前端优雅的实现列表排序功能”。它会被应用在哪些场景呢?这里举几个例子:
- 按照不同排序规则进行排序,例如:文章列表按更新时间升序或降序排列、按照浏览量升序或降序排列等等
- 前端实现搜索功能,按匹配度进行排序
- ……
面对这一问题,我们有几种方案备选,可以一起讨论一下
方案一:直接了当
直接绑定数据不就好啦。
我想很多前端从业者第一反应都会是这样思考的,当然我也不例外,这个方案的结构大致会是这个样子——
View层有一个listView与ViewModel层的listDate绑定,当需要重新排序的时候,对于listData重新sort一下,View层中的listView会自动更新。
没错,问题貌似解决了。但是当数据量达到一定程度或者列表中的结构比较复杂的时候,这个方案会很吃力。
拿我遇到的一个具体需求举个例子,我需要排序的是一系列化学反应方程式,比如:
2 N a H C O 3 + C a ( O H ) 2 = C a C O 3 ↓ + N a 2 C O 3 + 2 H 2 O 2NaHCO_3+Ca\left(OH\right)_2\xlongequal{ }{ }CaCO_3\downarrow +Na_2CO_3+2H_2O 2NaHCO3+Ca(OH)2 CaCO3↓+Na2CO3+2H2O
如果前端实现这样一个结构需要多少<span>
或其他标签,可想而知(尽管他不是最复杂的例子)。如果按照此方案对几千几百条这样的数据进行重新排序时,对于DomTree产生的负担是极大的。如果我理解没错的话,当下主流的前端架构(React、Vue、Angular等)大致会这样处理:
- listDate引用未发生变化(可能需要手动触发render)
- 逐一检查
listDate[index] === lastListDate[index]
- 如果不一致则将原Dom节点移除掉并构造新的Dom节点
- listDate引用发生了变化
- 将整个listView从DomTree上移除掉并进行重新构造
无论何种情况,都有大量的Dom结构的操作,这对于性能会带来一定的考验。
根据这个方案,完成了一个简单的Demo:
private invert() {this.listDate = [...this.listDate.reverse()];
}private render() {return (<div id="eq-list"><button id="invert-btn" onClick={() => {this.invert()}}>倒过来</button><ul class="equation-list">{this.getEqList()}</ul></div>);
}private getEqList() {return this.listDate.map(list => {return (<li class="equation-item"><equation eqlatex={list.latex}></equation></li>);});
}
这里我使用的是stenciljs框架,无需纠结语法。另外<equation>
是我封装的一个Web Component,用来根据latex展示化学反应方程式。
实现的效果是这样的:
由于数据量较大,在翻转的时候会卡顿 4 - 5 秒钟,故而这种方案貌似不太能接受。可以尝试一下其他方案。
方案二:多来几份
方案一的一个重要问题在于频繁的修改Dom结构,方案二便主要针对这一点进行优化与完善 —— 在初始化的时候将各种排序结果都渲染好,再根据具体的用户操作控制显示与隐藏。
也就是说它将方案一的 “每次都卡” 优化为 “只卡一次” ,那就是初始化的时候。
看似在一定程度上解决了排序卡顿用户体验差的问题,但是治标不治本。还是有大量的算力浪费掉了。
以上文的例子为例,依此方案解决,会出现同一个item的解析与渲染会重复多遍的问题。
那么问题来了,有没有办法在不动Dom结构的情况下,完成Dom上的排序呢?
方案三:flex - order
这个方案就是用来解决上一个方案提出的问题的。可以在不修改Dom Tree的前提下完成节点排序。
它主要运用的是 flex
布局下的 order
属性,来修改item在布局时的顺序。
有了它,我们就可以将排序与内容分开管理了。不再局限于元素在数组中的 index
了,可以大概采用这样的结构:
将每一个列表中的item分为两块:
- innerData,表示元素的内部数据,与listData绑定;
- itemOrder,表示元素的列表序,与orderDate绑定,当需要改排序方式时是需要维护好orderDate便可以了,由它去驱动列表的item的
order
属性发生变化便完成了排序任务。
还是上文那个例子,通过这一方案实现后,效果如下:
从实现效果上看,方案三明显优于方案一,几乎没有卡顿与延时的现象。
代码实现也很简单:
private updateInvert() {this.isInvert = !this.isInvert;
}private render() {return (<div id="eq-list"><button id="invert-btn" onClick={() => {this.updateInvert()}}>倒过来</button><ul class="equation-list">{this.getEqList()}</ul></div>)
}private getEqList() {return this.listDate.map((list, index) => {return (<li class="equation-item" style={{order: this.isInvert ? -index : index}}><nb-equation eqlatex={list.latex}></nb-equation></li>);});
}
关于 order
的补充
它作用于父容器display: flex
的子元素。
仅对元素在视觉上的顺序产生作用,并不会影响其 parent
的 children
上的顺序等逻辑顺序。
它作为一个Dom节点的一个属性,它接收一个整型的值,无论正整数、负整数、0都可以。如果传入浮点值则会视为未传入,取默认值0,并不会做任何取整操作。所以如果您是按匹配度排序的话,需要浮点数整型化后进行处理。
其视觉排序顺序是按照order
值由小到大排列的,即:小值在前,大值在后。同值则按照在Dom Tree上的顺序进行排列。
最后要说明的一点是:order
的浏览器兼容性还是不错的 ——
浏览器 | Chrome | Edge | Firefox | Safari | Opera |
---|---|---|---|---|---|
兼容性 | 29.0 + | 11.0 + | 28.0 + | 9.0 + | 17.0 + |
上表数据来源 w3cschoo : https://www.w3cschool.cn/cssref/css3-pr-order.html
所以放心大胆的使用吧。
巧用order实现列表排序相关推荐
- Hive中使用sort_array函数解决collet_list列表排序混乱问题
目录 0. 相关文章链接 1. 数据准备 2. 使用collect_list和concat_ws进行行转列 3. 使用sort_array函数解决collet_list列表排序混乱问题 0. 相关文章 ...
- python输入数字并排序_「每日一练」巧用Python实现数字排序
原标题:「每日一练」巧用Python实现数字排序 数字排序在我们的生产和生活中占着非常大的比重,这种思维和技术可以让一组数据更快更明了的展现在我们的面前,极大的提高了我们的工作效率! 那么,你知道如何 ...
- Python学习教程实用技法:通过公共键对字典列表排序—itemgetter
Python学习教程实用技法:通过公共键对字典列表排序-itemgetter 前言:我们有一个字典列表,想根据一个或多个字典中的值对列表进行排序. 利用operator模块中的itemgetter函数 ...
- 利用jQuery对无序列表排序 http://www.apkbus.com/android-80639-1-1.html
利用jQuery对无序列表排序的原理是:获取到无序列表中的所有列表项,并转成数组形式,使用JavaScript函数对其进行排序后再次输出.其中使用到的jQuery函数有ready().get().te ...
- python 3 字典排序_Python学习教程实用技法:通过公共键对字典列表排序—itemgetter...
Python学习教程实用技法:通过公共键对字典列表排序-itemgetter 前言:我们有一个字典列表,想根据一个或多个字典中的值对列表进行排序. 利用operator模块中的itemgetter函数 ...
- Python列表排序 reverse、sort、sorted 操作方法详解
python语言中的列表排序方法有三个:reverse反转/倒序排序.sort正序排序.sorted可以获取排序后的列表.在更高级python list排序中,后两中方法还可以加入条件参数进行排序. ...
- Python 列表排序方法reverse、sort、sorted详解
python语言中的列表排序方法有三个:reverse反转/倒序排序.sort正序排序.sorted可以获取排序后的列表.在更高级列表排序中,后两中方法还可以加入条件参数进行排序. reverse() ...
- mysql order by 中文 排序
mysql order by 中文 排序 1. 在MySQL中,我们经常会对一个字段进行排序查询,但进行中文排序和查找的时候,对汉字的排序和查找结果往往都是错误的. 这种情况在MySQL的很多版本中都 ...
- python 字符串比较忽略大小写的方法_python实现忽略大小写对字符串列表排序的方法...
本文实例讲述了python实现忽略大小写对字符串列表排序的方法,是非常实用的技巧.分享给大家供大家参考.具体分析如下: 先来看看如下代码: string = ''' the stirng Has ma ...
最新文章
- valgrind——Cachegrind分析CPU的cache命中率、丢失率,用于进行代码优化。
- 卫星对地观测及任务调度中日照分析
- python绘制滑稽脸_用Python画滑稽
- 空格分隔输出(信息学奥赛一本通-T1026)
- android keyguard,Android8.1 SystemUI Keyguard之指纹解锁流程
- 5G 爆发前夕,这些科技巨头们聚在一起“密谋”了些什么?!
- Http请求返回结果报UnsupportedCharsetException
- 计算机aero背景黑,Win7中Aero下面的主题变为黑色
- POJ 334932742151184020022503
- PyQt5 实现类似海康的设备搜索工具
- buuctf————[NPUCTF2020]你好sao啊
- 2022-2028年中国饮用水行业市场专项调研及投资前景研究报告
- uniapp 下载视频到本地
- 关于ECharts中调整容器与图表的位置关系
- 如何使用Kotlin构建Android旋转旋钮以帮助儿子练习钢琴
- 淘宝被列入黑名单,确有其事还是另有原因
- 手机端网页尺寸html,手机端网页设计尺寸_html/css_WEB-ITnose
- 应用于流形的卷积网络
- 编程实用工具大全(前后端皆可用,不来瞅瞅?)
- STATA如何保留和删除变量或者观测值