使用 hyperHTML,有没有办法直接绑定到要修改的元素而不是其父元素?

Using hyperHTML, is there a way to bind directly to an element to be modified rather than its parent?

假设我有以下内容:

<div id="parent">
  <div id="child-one"><p>Child One</p></div>
  <div id="child-two"><p>Child Two</p></div>
  <div id="child-three"><p>Child Three</p></div>
</div>

据我了解,hyperHTML 设置您绑定到的元素的 innerHTML。如果我不仅要更改 #child-two 的 innerHTML,还要更改其属性而不触及 #child-one 和 #child-three,使用 hyperHTML 实现此目的的最佳方法是什么?

有没有办法直接绑定到要修改的元素而不是其父元素?

我知道我可以使用 wire 创建一个新元素,然后完全替换现有元素,但那样我就无法继续绑定并只更新已更改的元素。

这里有一些误解,我会尝试解决所有这些问题。

As I understand it, hyperHTML sets the innerHTML ...

hyperHTML 不是 innerHTML

人们看到模板字面量,他们本能地认为它是 innerHTML,但 hyperHTML 是除了 innerHTML.

之外的一切

名称是故意相似的,但实现与字符串无关,字符串只是用于映射 "all the things" 并将逻辑粘合在一起的声明外观。

两者的区别:

  1. innerHTML 每次都会丢弃每个节点并从头开始创建所有内容,而 hyperHTML relate always see nodes to a specific context
  2. innerHTML 总是需要注入一个父元素,hyperHTMLwire 这也是你要找的,但我稍后会解释这个
  3. innerHTML 允许您定义损坏的布局,hyperHTML 如果您做错了什么并期待特定的语义(即没有部分属性恶作剧),
  4. 将会抛出

抱歉,如果您已经知道这一点,但我认为有必要澄清 hyperHTML 背后的根本概念。

现在,让我们继续:-)

Is there a way to bind directly to an element to be modified rather than its parent?

是的,the wire

I know I could use wire to create a new element and then completely replace the existing element, but then I would not have the ability to continue to bind and update only what has changed.

没有。 Wires have ids,因此每个 ID 将始终 return 完全相同的节点。

如果你想将 #child-two 连接到它的父级,但你也可以全局关联它,如果需要,你可以简单地通过一个 id 连接它。

const {bind, wire} = hyperHTML;

const outer = bind(document.body);
const inner = wire(document.body, ':child-two');

// you could wire inline but if you want
// to reuse the same node anywhere
// you need a callback to be sure the template literal
// is unique and not a different one each time (latest ES specs)
const child2 = model => inner`
  <div id="child-two" onclick=${model.onclick}>
    <p>${model.text}</p>
  </div>`;

// you can update the parent node every time you want
const update = model => {
  outer`
  <div id="parent" onclick=${model.onclick}>
    <div id="child-one"><p>Child One</p></div>
    ${
      // and pass along any DOM node or wire you want
      child2(model)
    }
    <div id="child-three"><p>Child Three</p></div>
  </div>`;
};

update({
  onclick(event) {
    // will log "parent" or "child-two"
    event.stopPropagation();
    console.log(event.currentTarget.id);
  },
  text: 'This is Child 2'
});

您可以在 code pen.

中实时测试以上代码