如何在内容更改后将hyperHTML重新渲染到同一元素

时间:2018-01-09 12:26:32

标签: javascript rendering hyperhtml

我正在尝试支持与React.Children

相同类型的事情

我的代码看起来像

const elem = document.getElementById("profile")
const render = hyperHTML.bind(elem);
const name = elem.textContent
render`<b>Hi ${name}</b>`

所以API看起来像

<div id="profile">alax</div>  <div id="profile"><b>Hi alax</b></div>

我正在使用MutationObserver重新报道内容更改

如果内容已更改。 hyperHTML表示它依赖于正确的元素..但元素保持其innerHtml(无更新)

我可以看到<!--_hyper: -2001947635;-->已删除,然后设置了内容,但设置了渲染&amp; hyperHTML.bind 再次无效

任何想法都会很棒! THX

更新

上述问题的解决方法是调用hyperHTML.bind``然后使用hyperHTML进行正常渲染

上下文 - 我使用hyperHTML创建自定义元素库(hyper-element

我的用例:我在混合技术项目中工作(有些人使用jQuery)

旁注,关于原因。我想支持像部分模板

这样的东西

部分模板的示例:

 <user-list data="[{name:'ann',url:''},{name:'bob',url:''}]">
     <div><a href="{#url}">{#name}</a></div>
 </user-list>

输出:

 <user-list data="[{name:'ann',url:''},{name:'bob',url:''}]">
     <div><a href="">ann</a></div>
     <div><a href="">bob</a></div>
 </user-list>

这是在您控制的元素中设置自定义内容的一种用法

目前,我通过三方工作/重新审核来设置内容

https://jsfiddle.net/k25e6ufv/16/

我现在的问题是:它正在重新发送另一个自定义元素并将传递内容传递给子元素

看起来hyperHTML正在将元素前面的子元素内容设置为元素,并在不设置内容的情况下创建元素

向下滚动到源代码底部以查看实施情况!

https://jsfiddle.net/k25e6ufv/14/

撕毁疯猫

  Html`
  xxx: ${this.wrapedContent} zzzz
  `

当前输出:

wrapedContent: ppp time:11:35:48 ~ crazy-cats: **Party 11:35:48** xxx: zzzz

<crazy-cats>Party 11:37:21 xxx: <!--_hyper: -362006176;--> zzzz </crazy-cats>

期望的输出:

wrapedContent: ppp time:11:35:48 ~ crazy-cats: xxx: **Party 11:35:48** zzzz

<crazy-cats> xxx: Party 11:37:21 zzzz </crazy-cats>

1 个答案:

答案 0 :(得分:1)

我会尽力回答,但我会开始说,在寻求帮助时,更容易/更好地展示您尝试解决的最简单的用例。

周围有很多&#34;&#34;您的小提琴中的代码,以便我尝试仅回答hyperHTML相关位。

超元素?

我不确定图书馆的目标是什么,但hyperHTML公开了hyper.Component,还有一个官方HyperHTMLElement class要扩展,这大多数都是您在示例中手动实现的内容。

我会继续回答您的问题,但请考虑尝试,至少是官方替代方案,如果需要可能会推动一些改变。

部分模板

hyperHTML 模式和强度是Template Literal标准。因此,要从DOM生成TL,需要解析内容或代码评估。这两种解决方案都没有办法。

自定义元素需要JavaScript才能工作,如果没有JS,您的部分模板将毫无用处,并且可能会让用户/消费者感到困惑。

您不想定义如何处理布局中的data,您希望在定义它的类中定义自定义元素行为。

这意味着:摆脱旧式的DOM内输出,只需使用Custom Element类来定义其内容。您只维护相关类,而不是维护一个不知道CE应如何表示该数据的布局。

TL; DR 以下是一个糟糕的hyperHTML模式:

<user-list data="[{name:'ann',url:''},{name:'bob',url:''}]">
  <div><a href="{#url}">{#name}</a></div>
</user-list>

你要做的就是写下这个:

<user-list data="[{name:'ann',url:''},{name:'bob',url:''}]"></user-list>

但是小心data中的hyperHTML属性仅在通过模板文字传递时才是特殊的。如果要将JSON传递给组件,请以不同方式调用该属性。

// hyperHTML data is special, no need to use JSON
render`<c-e data=${{as: 'it is'}}></c-e>`

上面的代码段不同于将JSON作为数据属性文本,因此您的示例应使用data-json名称,并且该类应记住其构造函数中的JSON.parse(this.dataset.json)(或者具有执行此操作的属性观察者你)

hyperHTML拥有元素

当你写:

  

看起来hyperHTML正在将元素的前面内容设置为元素,并在不设置内容的情况下创建元素

你认为你应该关心hyperHTML所做的事情:你不应该这样做。

您唯一应该理解的是hyperHTML拥有它处理的节点。如果您通过不同的库或手动删除这些节点,那么您做错了。

hyperHTML(document.body)`<p>hello ${'world'}</p>`;
// obtrusive libraries ... later on ...
document.body.textContent = 'bye bye';
// hyperHTML still owns the body content
hyperHTML(document.body)`<p>hello ${'world'}</p>`;

上面的片段完全没问题,完全错了。 您不会手动更新body内容,也不会通过jQuery或其他图书馆干扰其内容,您根本不应该删除内容。

一旦您选择hyperHTML来处理绑定的上下文,那么您已经做出了选择。

这个世界上几乎每个图书馆都是如此。如果你使用Angular来创建一些东西而你通过jQuery搞得一团糟,那就会破坏。如果您编写主干模板,然后手动将其内容弄乱,那就会中断。

如果将一个元素绑定到hyperHTML并将其与其他库混淆,则会中断。

唯一不会破坏的是电线,这意味着你创建电线的那一刻,你可以直接附加它,它实际上是一个DOM节点,所以它会在那里,它将被处理hyperHTML

然而,您应该使用hyperHTML来处理这些更改,而不是jQuery或JS本身。

输出正确

当你说输出不应该包含评论时,你假设你应该关心通过hyperHTML产生什么输出:你不应该!

hyperHTML使用注释作为分隔符,这些对于性能,不受重绘和重排以及部分更改(如下所示)都非常好:

hyperHTML(document.body)`<p>${'a'} b ${'c'}</p>`

ac都会将评论作为主播节点,以便稍后可以使用任何内容更新其内容。

hyperHTML(document.body)`<p>${[list, of, nodes]} b ${otherThing}</p>`

你改变插值?好的,hyperHTML知道要替换什么以及在哪里。

强制拥有内容

如果您使用其他模板文字来重新填充绑定节点,则会破坏缓存并创建新内容。

此时您最好使用innerHTML,因为hyperHTML的所有功能都将消失。

首先,如果您的内容变化太大,请使用数组。

hyper(document.body)`${['text']}`;
// you can clean up the text through empty array
hyper(document.body)`${[]}`;
// re-populate it with new content
hyper(document.body)`${['a', 'b', 'c']}`;

上面的示例仍然比更改模板更好,因为内容的所有优化都已存在。

但是,如果您想确定通过hyperHTML创建的初始节点,假设没有第三部分脚本变异/废弃该节点,则可以使用电线。

const body = hyper()`<p>my ${'content'}</p>`;
document.body.textContent = '';
document.body.appendChild(body);

它有点极端,但至少更快。

作为摘要

看起来你正试图将hyperHTML潜入一个应用程序,该应用程序一直通过不同的第三方库来破坏布局。

除非你创建一个封闭的Shadow DOM引用并且你通过布局删除部分模板,否则你总是会遇到基于DOM内容副作用的库问题,这些库会改变他们不拥有的元素。< / p>

hyperHTML中,所有权概念是关键,就像在React中你无法在运行时更改组件的已定义JSX时,你永远不应该尝试在运行时更改{{1的定义模板文字}}

现在,尽管我想解决您的所有问题,但我觉得问您是对的:您确定hyperHTML是否真的是您当前应用的解决方案?如果您不使用封闭模式Shadow DOM和hyperHTML 来更新您的DOM,那么由第三方库引起的周围副作用看起来会不断打破您的期望。