【问题标题】:Use of Template with HTML Custom Elements使用带有 HTML 自定义元素的模板
【发布时间】:2018-09-21 02:53:03
【问题描述】:

我刚开始学习 HTML 自定义元素,通过阅读一系列介绍、教程和文档,我认为我对它的工作原理有了很好的了解,但我对正确使用方法有一个哲学问题或不使用<template> 标签。

自定义元素使您能够封装新功能,简化 HTML 文档的结构,并允许您简单地插入 <my-custom-element>...</my-custom-element> 标记而不是 <div class="my-custom-element"><span class="part1">...</span><span class="part2">...</span></div>

元素的类定义然后设置该元素的结构和功能。然后一堆教程描述了如何使用<template>...</template><slot>...</slot> 来设置自定义元素的内容。然后,您必须在要使用该元素的每个 HTML 文档中包含模板代码,而不是在自定义元素类的构造函数中设置它。这是否与自定义元素有助于简化和封装功能以使其更便携的事实背道而驰?还是我误解了文档中模板的正确使用和/或放置方式?

通过 SO,我能找到最接近解决这个问题的是这个问题:

How to stamp out template in self contained custom elements with vanilla js?

但答案基本上回避了这一切并说“不要使用<template>”,因此并没有真正消除我的困惑。

【问题讨论】:

    标签: javascript html web-component custom-element html5-template


    【解决方案1】:

    实际上<template>元素可以通过HTML Imports从另一个文档中导入,以及定义自定义元素的Javascript代码:

    <link rel="import" src="my-custom-element.html">
    ...
    <custom-element></custom-element>
    

    所以它不需要包含在每个 HTML 文档中。 This post shows a minimal example.

    HTML 导入仅在 Chrome 和 Opera 中实现。如果你想在 Firefox 和 Safari 中使用它们,你需要使用 HTML Imports polyfill

    另一方面,目前,Mozilla 和 Apple 不打算在各自的浏览器中本地实现 HTML 导入。因此,他们建议使用纯 Javascript 模块(使用 import&lt;script src="..."&gt;)定义自定义元素,并改为推广 template literals 字符串,这提供了一些优势(变量、函数),但有时在 IDE 中编码更复杂(因为它们的字符串表示)。

    也许在未来standard HTML modules 会被所有浏览器采用,&lt;template&gt; 会重新成为人们关注的焦点......

    请注意,如果没有 HTML Imports,您仍然可以使用 fetch() 自己导入一些 HTML 文档:

    fetch( "template.html" )
        .then( stream => stream.text() )
        .then( text => 
            customElements.define( "c-e", class extends HTMLElement {
                constructor() {
                    super()
                    this.attachShadow( { mode: 'open'} )
                        .innerHTML = text
                }
            } )
        )
    

    2019 年更新

    HTML 导入 won't be supported natively after Chrome 73。然后,您应该使用上面列出的其他解决方案(polyfill、备用模块加载器、JS import,或使用 fetch 直接下载)。

    【讨论】:

    • 谢谢,我不知道 HTML 导入,听起来是正确的解决方案。但是由于缺乏支持,我是否正确理解您正在提倡模板文字字符串?如果是这样,我仍然有一个问题,为什么不在自定义元素的 JS 类中以编程方式构建元素?在我看来,在 JS 中包含一大块 HTML 作为字符串是不必要的复杂化。
    • HTML 导入是正确的解决方案...直到 9 月 Google 宣布将弃用该功能 (stackoverflow.com/q/52791470/4600982)。实际上我提倡 HTML 导入(使用 polyfill),但现在...... :-( 作为开发人员和设计师,我认为将 HTML 文档用于模板是比模板文字更好的做法,但来自 Google,尤其是 Mozilla 和 Apple 的人似乎有其他兴趣...有些人不是在正确的地方:2018年世界第一个平台仍然没有导入功能。你能相信吗?
    • 有趣。谢谢你的帮助!那么,我倾向于以编程方式构建事物。与调用位于我的 JS 文件中其他位置的模板文字字符串相比,将自定义元素的组件与实现它的类放在一起构建自定义元素的组件对我来说似乎更具可读性。但也许这只是因为我最初来自 C++/Java 背景,不赞成将大量数据或内容放在一个大字符串中。
    • @Supersharp 你会在“template.html”中定义一个完整的 HTML 文件,还是只定义按钮等 html 元素?
    • @J.Doe 只是 html 内容
    【解决方案2】:

    免责声明:我是下面提到的rich-component 库的作者。

    在对自定义元素进行了一段时间的试验并最近提出了一个完全基于它们的完整项目之后,我想分享我对此的见解:

    • 任何微小的组件都可以长成某种野兽
    • 其中的 HTML 部分可能会增长到非常不方便将其保留在 JS 中的程度
    • 使用模板,构建和解析一次,然后克隆并注入到影子根中 - 这与使用文档片段而不是改变活的 DOM 是相同的最佳实践
    • 如果模板内容应该从组件的实例更改为实例 - 可能会使用某种数据绑定框架,并且如果采用极简方法 - 处理克隆源可能仍然更容易且性能更高-模板文档片段而不是对字符串或模板文字进行操作

    为了不重复写同样的几十行,我准备了rich-component库,其中:

    • 规范了一些用于模板配置的 API 以及所有那些“克隆模板、创建影子、将模板的内容注入其中”的重复代码行
    • 已知会在提供 html URL 时获取 html 内容
    • 缓存模板,因此只进行一次提取

    【讨论】:

      猜你喜欢
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多