Angular11 keyvalue管道遍历Map保留原插入顺序异常问题求助
问题根因
- 你实现的
originalOrder比较器不符合ECMAScript规范对Array.sort()比较函数的约束:标准要求比较器必须返回负数、正数、0来分别对应a小于b、a大于b、a等于b的判断,始终返回0属于不符合规范的用法,不同JS引擎的排序算法实现会对这种输入产生不可预期的结果,这是顺序错乱的核心原因。 - Angular
keyvalue管道的底层逻辑是先将Map的键值对转换为数组,再调用传入的比较器对数组执行排序,所以比较器不符合规范时,不同运行环境的表现差异是必然的,仅在模拟器复现不是巧合:模拟器的webview内核版本、实现逻辑和本地开发浏览器、真机系统webview存在差异,部分旧版内核的排序算法在所有比较都返回0时不会保留原始顺序,甚至会出现元素错位。 - 你观测到比较器传入的key顺序和原始插入顺序不符属于排序算法的正常表现:排序过程中会随机取出元素两两比较,不会按原始顺序传入参数,和Map本身的顺序无关。
修复方案
方案1:直接使用Map原生迭代器(最稳妥,完全规避排序逻辑)
无需使用keyvalue管道,直接遍历Map的entries()迭代器即可保留原始插入顺序:
组件侧先将迭代器转为数组:
// 组件代码 getOrgArray() { return Array.from(this.mappingMap.organisations.entries()); }
模板中直接遍历:
<ng-container *ngFor="let [key, value] of getOrgArray(); let i = index"> <!-- 原有业务逻辑 --> </ng-container>
方案2:调整keyvalue管道的比较器逻辑
如果必须使用keyvalue管道,基于你value中自带的sliderIndex字段做排序,完全规避运行环境差异:
originalOrder = (a: KeyValue<number,MappingMapvalue>, b: KeyValue<number,MappingMapvalue>): number => { return a.value.sliderIndex - b.value.sliderIndex; }
内容的提问来源于stack exchange,提问作者fricko
相关产品推荐
相关产品推荐

