首页 > 解决方案 > 订单质量

问题描述

我喜欢在页面显示时动态地用不同的 HTML 替换 HTML。目前,我有,old.innerHTML = new.innerHTML但这有对应的:

  1. 进行<input>文本编辑将丢失用户编写的文本。
  2. 进行<input>文本编辑将失去焦点。
  3. 每个 CSS 关键帧动画都会重新启动,即使节点保持不变。

所以我最终不得不一步一步地更新每个节点。如果我将 DOMTree 划分为节点并递归比较每个节点的子节点,那应该不会那么难。

在伪代码中,我递归执行此方法

  1. 从当前中删除新的(工作)中不存在的节点
  2. 将节点添加到仅存在于新(工作)中的当前节点
  3. 当前的订单节点以匹配新的订单(我在这里存货)
  4. 如果存在,则对每个子节点重复。

要知道哪个 current-structure-child 与 new-structure-child 最匹配,我使用了一个function elementEquality(a,b)计算分数。

在第 1 步和第 2 步之后,我有以下节点:

因此,在从第 3 步开始的示例中,我有这样的节点:

 current  new        | elementEquality(a,b)-result
--------+------------+------
<!--->  | #text b    | 0
<div>   | <div>      | 50
#text b | <!--->     | 0
--------+------------+------
                       50 total quality points

我的意思是我们看到当前结构必须交换第一个和第三个元素以匹配新的顺序。结果将是这样的:

--  solution is

 current  new        | elementEquality(a,b)-result
--------+------------+------
#text b | #text b    | 10
<div>   | <div>      | 50
<!--->  | <!--->     | 5
--------+------------+------
                       65 total quality points

我们可以用我们的思想来做到这一点,但我想以编程方式做到这一点。

我现在的问题是,如何决定:

  1. 质量可以提高。
  2. 应该交换哪些元素。

一种方法是用蛮力方式限定每个可能的解决方案。但是有 1 个节点有 1 个可能的解决方案,有 2 个节点有 2 个可能的解决方案,3 个节点有 7 个可能的解决方案(你看,它是指数的)。

标签: javascripthtml

解决方案


似乎您的目标是重新发明轮子 - morphDOM 完全符合您的要求:

https://github.com/patrick-steele-idem/morphdom

从自述文件:

用于变形现有 DOM 节点树以匹配目标 DOM 节点树的轻量级模块。它速度很快,并且可以与真实的 DOM 一起使用——不需要虚拟 DOM!

创建此模块是为了解决更新 DOM 以响应 UI 组件或页面被重新呈现的问题。更新 DOM 的一种方法是简单地丢弃现有的 DOM 树并用新的 DOM 树替换它(例如,myContainer.innerHTML = newHTML)。虽然用全新的 DOM 树替换现有的 DOM 树实际上会非常快,但这是有代价的。代价是与现有 DOM 节点相关的所有内部状态(滚动位置、输入插入符号位置、CSS 转换状态等)都将丢失。我们不想用新的 DOM 树替换现有的 DOM 树,而是要转换现有的 DOM 树以匹配新的 DOM 树,同时尽量减少对现有 DOM 树的更改次数。这正是 morphdom 模块所做的!

morphdom 不依赖于任何虚拟 DOM 抽象。因为 morphdom 使用的是真实的 DOM,所以 Web 浏览器维护的 DOM 将永远是事实的来源。即使您有手动操作 DOM 的代码,事情仍然会按预期工作。此外,morphdom 可以与任何生成 HTML 字符串的模板语言一起使用。

转换是在原始 DOM 树和目标 DOM 树的单次传递中完成的,旨在最大限度地减少对 DOM 的更改,同时仍确保变形的 DOM 与目标 DOM 完全匹配。此外,该模块使用的算法将自动匹配具有相应 ID 并且在原始和目标 DOM 树中都找到的元素。


推荐阅读