javascript - 为什么在手动重新排序和恢复 dom 项目后,淘汰模板绑定停止工作?
问题描述
我正在使用淘汰赛 foreach (更具体地说,template: { foreach: items }
)绑定来显示元素列表。然后我继续采取以下行动:
- 交换可观察数组的第一个和第二个元素。正如预期的那样,我看到屏幕上反映的变化。
- 重复上一个操作以恢复到初始状态。同样,这按预期工作。
- 现在,交换第一个和第二个 DOM 元素。正如预期的那样,我看到屏幕上反映的变化。
- 重复上一个操作以恢复到初始状态。同样,这按预期工作。
尽管我们已经手动篡改了 DOM,但我们已经完全恢复到初始状态,而在 DOM 篡改期间没有调用敲除。这意味着状态恢复到最后一次淘汰赛意识到它,所以它应该看起来像淘汰赛一样,好像什么都没有改变一样开始。但是,如果我再次执行第一个操作,即交换数组中的前两个元素,则更改不会反映在屏幕上。
这是一个 jsfiddle 来说明问题:https ://jsfiddle.net/k7u5wep9/ 。
我知道手动篡改由淘汰赛管理的 DOM 是一个坏主意,并且可能导致未定义的行为。不幸的是,由于第三方代码,这在我的情况下是不可避免的。让我难过的是,即使在将手动编辑恢复到确切的初始状态之后,淘汰赛仍然无法按预期工作。
我的问题是:是什么导致了这种行为?然后,如何解决它?
解决方案
事实证明,这里并没有什么神奇的事情发生。我犯的错误是只考虑元素而不是所有节点。淘汰模板绑定在重新排序时保留所有节点的记录,而不仅仅是元素。
在手动编辑 DOM 之前,模板绑定的子节点为:
NodeList(6) [text, div, text, text, div, text]
.
使用手动交换前两个元素parent.insertBefore(parent.children[1], parent.children[0])
后,变为:
NodeList(6) [text, div, div, text, text, text]
.
重复该动作产生:
NodeList(6) [text, div, div, text, text, text]
.
虽然这与仅引用元素时的初始状态相同,但引用所有节点时则完全不同。
解决方案现在变得清晰。执行正确手动交换的一种方法是替换
parent.insertBefore(parent.children[1], parent.children[0]);
和
let nexts = [parent.children[0].nextSibling, parent.children[1].nextSibling];
parent.insertBefore(parent.children[1], nexts[0]);
parent.insertBefore(parent.children[0], nexts[1]);
如https://jsfiddle.net/k7u5wep9/2/中所示。
显然,当之前/之后没有文本节点时必须更加小心,但想法保持不变。
推荐阅读
- c++ - 如何“溢出”超出特定范围的值(如 30 - 100)
- asp.net - asp:RequiredFieldValidator 定位和可见性,向下滚动保存按钮
- angular - 将 Git/TFS 远程仓库配置为两个本地仓库
- apache-kafka - kotlin @RegisterExtension 不与salesforce kafka-junit5 一起使用
- reactjs - 安装第三方库后出现 React Native 错误
- react-native - React Native Slider - onValueChange 调用了太多次
- ruby - ruby 中区域之间的 S3 copy_object
- java - 在 NodeJS 和 Java 中计算 HMAC sha-512
- android - 如何在android avd虚拟设备中重新挂载只读系统文件夹
- python - 如何创建不需要导入的函数?(在 Python 中)