hyperhtml - 有没有一种方法/解决方法可以在不使用 Shadow DOM 的情况下在 hyperHTML 中使用插槽原理?

标签 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>

虽然有好处,但我不喜欢使用 Shadow DOM 的一些原因:
  • 我想看看我是否可以转换我现有的 SPA:所有必需的 CSS 样式现在都存在于 SASS 文件中,并被编译为 1 个 CSS 文件。在 Shadow DOM 组件中使用全局 CSS is not easily possible我不想解开 SASS(现在)
  • Shadow DOM 有一些性能成本
  • 我不希望大型 Shadow DOM polyfill 有插槽 ( webcomponents-lite.js : 84KB - 未缩小)
  • 最佳答案

    让我开始描述什么是插槽以及它们解决了什么问题。

    刚刚停放的数据

    在你的布局中有槽是 HTML 尝试让你在布局中放置一些数据,然后通过 JavaScript 处理它。

    你甚至不需要 Shadow DOM 来使用插槽,你只需要一个带有命名插槽的模板来放置值。

        <user-data>
          <img  src="..." slot="avatar">
          <span slot="nick-name">...</span>
          <span slot="full-name">...</span>
        </user-data>
    

    你能发现那个组件和下面的 JavaScript 之间的区别吗?

        const userData = {
          avatar: '...',
          nickName: '...',
          fullName: '...'
        };
    

    换句话说,通过像下面这样的函数,我们已经可以将槽转换为由属性寻址的有用数据。

        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;
        }
    

    插槽作为 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>`;
        });
    

    但是,如果我们想使用 Shadow DOM 来保护样式和节点免受不希望的页面/第三部分污染,我们可以按照 this Code Pen example 所示进行操作。基于自定义元素。

    如您所见,唯一需要的 API 是 attachShadow API,并且有一个 super lightweight polyfill for just that重量为 1.6K 最小压缩。

    最后,但并非最不重要的是,您可以在 hyperHTML 模板文字中使用插槽并让浏览器进行转换,但这将需要更重的 polyfill,我不建议在生产中使用它,特别是当有更好更轻的替代方案时,如下所示。

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

    关于hyperhtml - 有没有一种方法/解决方法可以在不使用 Shadow DOM 的情况下在 hyperHTML 中使用插槽原理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48726904/

    相关文章:

    javascript - HyperHTML - 是否可以在不重新渲染整个组件 DOM 的情况下更新组件状态?

    javascript - 如何缩小Lit-HTML(包括注释)

    Mobx 观察者模式支持

    javascript - AFrame 内容无法在使用 hyperHTML 的 Chrome 上呈现

    javascript - 将 hyperhtml-element 与 browserify/babelify 捆绑在一起不起作用

    javascript - 重新排序 DOM 节点时的 HyperHTML 性能

    javascript - HTML <template> 元素与 Javascript 模板文字

    javascript - hyperHTML:更新列表

    javascript - 如何在 hyperHTML 中动态更改标签