Nativescript Vue中对象数组的正确排序方法 切换升降序结果异常
NativeScript Vue 数组排序异常的问题排查与修复
核心异常根源
很多人用原生数组sort方法都会踩这个坑:Array.sort() 是原地修改原数组的实现,调用后会直接改动原数组的元素顺序,不会返回一个独立的排序副本给你。
你现在在 orderedItems 计算属性里直接写return this.items.sort(...),等于每次算排序结果的时候,都直接把data里存的原始items数组给改了:
- 首次加载的时候,原始数组是没排序的乱序状态,第一次算升序的结果是对的,但算完之后原始数组已经被原地改成升序了
- 切到降序的时候,你的排序逻辑是基于已经被改过的升序数组做原地排序,排完之后原始数组又被改成降序了
- 来回点几次切换按钮之后,原始数组的状态已经被多次原地修改搅乱了,最后就会出现顺序完全不对,哪怕切回升序也排不对的情况。
修复实现
改法很简单:排序之前先把原数组拷一份独立副本,对副本做排序,绝对不要在计算属性里动原始数据:
computed: { orderedItems() { // 用展开运算符生成新数组,和原始items完全独立,排序不会改原数据 return [...this.items].sort((a, b) => { return this.sortAscending ? a.id - b.id : b.id - a.id; }); } }
这么改的好处:
- 每次计算排序结果的时候,都是从从来没被改过的原始items数据出发,不会被上一次排序的状态干扰
- Vue的计算属性依赖追踪逻辑完全正常,切换排序方向的状态时会正确触发重算,不会有渲染延迟或者顺序错乱的问题
常见误区澄清
- 这个问题和v-for的绑定位置没关系,也不是computed计算属性本身有什么副作用,就是原地排序改了原数据导致的状态污染
- 完全没必要改用watch监听排序方向去手动改items数组,计算属性本来就适合做排序、过滤这类派生数据的场景,只要不碰原数据,就能稳定运行
- 你之前看的NativeScript端大数组排序异常的问题,是移动端JS引擎的排序实现兼容bug,和你现在遇到的问题完全不是一回事,不需要做额外的平台适配
内容的提问来源于stack exchange,提问作者Mike Smedley
相关产品推荐
相关产品推荐

