1

我正在尝试支持与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;-->设置渲染hyperHTML.bind无济于事

任何想法都会很棒!谢谢


更新

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

上下文- 我正在使用 hyperHTML 创建自定义元素库(超元素

我的用例:我在一个混合技术项目中工作(有些人使用 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>

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

目前我通过 3 方工作/重新渲染设置内容

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


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

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

向下滚动到源代码的底部以查看实现!

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

Rending crazy-cats :

  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>
4

1 回答 1

1

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

您的小提琴中有很多“周边”代码,因此我将尝试仅回答hyperHTML相关位。


超元素 ?

我不确定这个库的目标是什么,但是hyperHTML暴露了hyper.Component,还有一个官方的HyperHTMLElement 类要扩展,它可以完成您在示例中手动实现的大部分事情。

我会继续回答您的问题,但请考虑至少尝试官方替代方案,并在需要时推动一些更改。


部分模板

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

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

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

这意味着:摆脱旧式的 DOM 输出,只需使用自定义元素类来定义其内容。您只维护相关类,而不是维护不知道 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属性 in才是特殊的。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 内容副作用的库的问题,这些库会改变他们不拥有的元素。

hyperHTML所有权概念是关键,就像你不能在React运行时更改为组件定义的 JSX,你永远不应该尝试在运行时更改为hyperHTML.

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

于 2018-01-10T13:26:58.033 回答