有没有办法/解决方法在hyperHTML中使用插槽原则而不使用Shadow DOM?

Jo *_*VdB 3 hyperhtml

我喜欢hyperHtml和lit-html的简单性,它们使用"标记模板文字"来仅更新模板的"可变部分".简单的javascript,不需要虚拟DOM代码和推荐的不可变状态.

我想尝试使用hyperHtml的自定义元素尽可能简单,支持<slot/>模板中的原则,但没有Shadow DOM.如果我理解正确,只有Shadow DOM才能使用插槽?

有没有办法或解决方法<slot/>在不使用Shadow DOM的情况下使用hyperHTML中的原则?

    <my-popup>
      <h1>Title</h1>
      <my-button>Close<my-button>
    </my-popup>
Run Code Online (Sandbox Code Playgroud)

虽然有好处,但有些原因我不喜欢使用Shadow DOM:

  • 我想看看我是否可以转换现有的SPA:所有必需的CSS样式现在都存在于SASS文件中,并编译为1个CSS文件.在Shadow DOM组件中使用全局CSS 是不可能的,我不想解开SASS(现在)
  • Shadow DOM有一些性能成本
  • 我不希望大型Shadow DOM polyfill有插槽(webcomponents-lite.js:84KB - unminified)

And*_*chi 8

让我开始描述什么是插槽以及这些解决了什么问题.

只是停放数据

在您的布局中有插槽是HTML尝试让您在布局中停放一些数据,并在稍后通过JavaScript解决它.

你甚至不需要Shadow DOM来使用插槽,你只需要一个带有命名插槽的模板,它将把值放在适当的位置.

    <user-data>
      <img  src="..." slot="avatar">
      <span slot="nick-name">...</span>
      <span slot="full-name">...</span>
    </user-data>
Run Code Online (Sandbox Code Playgroud)

你能发现该组件与以下JavaScript之间的区别吗?

    const userData = {
      avatar: '...',
      nickName: '...',
      fullName: '...'
    };
Run Code Online (Sandbox Code Playgroud)

换句话说,使用类似下面的函数,我们已经可以将插槽转换为属性寻址的有用数据.

    function slotsAsData(parent) {
      const data = {};
      parent.querySelectorAll('[slot]').forEach(el => {
        // convert 'nick-name' into 'nickName' for easy JS access
        // set the *DOM node* as data property value
        data[el.getAttribute('slot').replace(
          /-(\w)/g,
          ($0, $1) => $1.toUpperCase())
        ] = el; // <- this is a DOM node, not a string ;-)
      });
      return data;
    }
Run Code Online (Sandbox Code Playgroud)

插槽作为hyperHTML插值

既然我们有办法解决插槽问题,我们所需要的只是将它们放置在布局中.

从理论上讲,我们不需要自定义元素来实现它.

    document.querySelectorAll('user-data').forEach(el => {
      // retrieve slots as data
      const data = slotsAsData(el);
      // place data within a more complex template
      hyperHTML.bind(el)`
        <div class="user">
          <div class="avatar">
            ${data.avatar}
          </div>
          ${data.nickName}
          ${data.fullName}
        </div>`;
    });
Run Code Online (Sandbox Code Playgroud)

但是,如果我们想使用Shadow DOM来保证样式和节点免受不良页面/第三部分污染的影响,我们可以按照基于自定义元素的此代码笔示例中的说明进行操作.

正如您所看到的,唯一需要的API是attachShadow one,并且有一个超轻量级的 polyfill,重量只有1.6K min-zipped.

最后,但并非最不重要的是,您可以在hyperHTML模板文字中使用插槽并让浏览器进行转换,但这需要更重的polyfill,我不会在生产中推荐它,特别是当有更好更轻的替代品时,如此处所示.

我希望这个答案对你有帮助.