您如何避免丢失元素引用的克隆模板?

时间:2018-12-06 12:15:48

标签: hyperhtml

我注意到hyperHTML保留了我对元素的引用:

let div = document.createElement("div");
div.textContent = "Before Update";
hyperHTML.bind(document.body)`static1 - ${div} - static2`;
div.textContent = "After Update";

上方将显示一个页面,内容为:

static1 - After Update - static2

据我了解,hyperHTML最终会克隆HTML <tempate>元素以呈现最终输出。但是,克隆HTML模板时(例如上例中的变量“ div”),通常不会丢失引用吗?

因此,在初始渲染时,hyperHTML是否在克隆HTML模板后以某种方式将克隆的元素替换为其原始元素?

这是我认为的工作方式:

  1. 同时创建原始模板文字的HTML模板 用注释替换所有插值。
  2. 克隆带有注释的html模板。
  3. 从最初收到的每个插值中提取元素或文档碎片
  4. 使用其已处理插值替换克隆中的每个注释。

这正确吗?

1 个答案:

答案 0 :(得分:4)

我不确定这里的问题是什么,但是也有documentation pagevarious examples来了解如何使用hyperHTML,这与您使用它的方式并不完全相同。 / p>

实际上,由于hyperHTML是声明性的,因此不需要在其中引用任何内容,所以您宁愿这样写:

function update(text) {
  var render = hyperHTML.bind(document.body);
  render`static1 - <div>${text}</div> - static2`;
}

并在需要时致电update("any text")

  

这就是我的想法……这是正确的吗?

不,不是。 hyperHTML不会按照您所描述的方式克隆任何内容,而是将每个唯一的模板标签(经过净化处理的版本)与输出关联一次,并找出其中的所有内插孔。

该库中执行此操作的部分称为domtagger,每个模板文字的映射均基于标准事实,即它们在每个作用域中都是唯一的:

const templates = [];
function addTemplate(template, value) {
  templates.push(template);
  return template.join(value);
}
function asTemplate(value) {
  return addTemplate`number ${value}!`;
}
asTemplate(1);
asTemplate(2);
asTemplate(Math.random());
templates[0] === templates[1]; // true
templates[1] === templates[2]; // true
// it is always the same template object!

此后,使用同一标记模板的其他任何元素都会对该片段进行克隆,并使用地图查找一次孔,并采用一些复杂的逻辑来避免替换已知的任何内容,例如文本,属性,事件,或任何其他类型的节点。

hyperHTML永远不会删除注释,它将注释用作引脚,然后在需要更新任何内容时使用domdiff最终更新与这些引脚相关的节点。

Domdiff是petit-dom算法的无vDOM实现,而反过来又基于EW Myers的“ O(ND)差分算法及其变体paper

每当漏洞中包含DOM节点时,hyperHTML就会理解这一点,并用这些节点填充这些漏洞。如果您重复传递相同的节点,hyperHTML将不会做任何事情,因为它充满了算法和明智的决定,所有这些都在文档中进行了描述,以便从其抽象中获得最佳性能。

所有这些东西以及更多的东西,对于任何浏览器都已标准化,一旦缩小并压缩,hyperHTML的权重约为7K,它还提供了以下功能:

  • 自定义元素,例如通过已连接/已断开的侦听器的钩子
  • 通过hyperHTML.Component
  • 轻量级组件
  • 通过内容或通过有线方式操纵SVG
  • 通过HyperHTMLElement类
  • 简单的自定义元素定义

作为总结,如果您需要这些简化操作并且不想重新发明轮子,我建议您尝试一下。

如果您只是想了解其工作原理,则无需承担任何责任,因为该项目是完全开源的。

到目前为止,我从您的问题中读到的所有内容都是,您只是相信了解它是如何工作的,因此希望在此答复中,我整理了您需要完全理解的所有遗漏之处。

您要编写自己的lit / hyperHTML库吗?继续,也可以随意使用domtagger或domdiff库,很少其他人已经在做同样的事情。