模板与 HTML 自定义元素的使用

IT技术 javascript html web-component custom-element html5-template
2021-03-11 07:15:13

我刚开始学习 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,我能找到的最接近解决这个问题的是这个问题:

如何使用vanilla js在自包含的自定义元素中删除模板?

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

2个回答

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

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

所以它不需要包含在每个 HTML 文档中。这篇文章展示了一个最小的例子。

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

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

也许将来所有浏览器都会采用标准的 HTML module,并<template>重新成为人们关注的焦点……

请注意,如果没有 HTML 导入,您仍然可以使用以下命令导入一些 HTML 文档fetch()

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 年更新

在 Chrome 73 之后本机将不支持HTML 导入然后,您应该使用上面列出的其他解决方案(polyfill、替代module加载器、JSimport或直接下载fetch)。

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

免责声明:我是下面提到丰富组件的作者

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

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

为了不一遍又一遍地写同样的几十行,我准备了丰富的组件库,它:

  • 标准化一些用于模板配置的 API 以及所有那些“克隆模板、创建阴影、将模板的内容注入其中”的重复代码行
  • 已知在提供 html URL 时获取 html 内容
  • 缓存模板,以便获取只完成一次