简体   繁体   English

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

[英]Use of Template with HTML Custom Elements

I just started learning about the HTML custom elements, and through reading a series of intros, tutorials, and documentation, I think I have a good handle on how it works, but I have a philosophical question on the proper way to use or not use the <template> tag.我刚开始学习 HTML 自定义元素,通过阅读一系列介绍、教程和文档,我认为我对它的工作原理有了很好的了解,但我对正确使用或不使用的方法有一个哲学问题<template>标签。

Custom elements give you the ability to encapsulate new functionality, simplifying the structure of your HTML document, and allowing you to simply insert a <my-custom-element>...</my-custom-element> tag instead of <div class="my-custom-element"><span class="part1">...</span><span class="part2">...</span></div> .自定义元素使您能够封装新功能,简化 HTML 文档的结构,并允许您简单地插入<my-custom-element>...</my-custom-element>标签而不是<div class="my-custom-element"><span class="part1">...</span><span class="part2">...</span></div>

The class definition for the element then sets up the structure and functionality of that element.元素的类定义然后设置该元素的结构和功能。 A bunch of the tutorials then describe how to use <template>...</template> and <slot>...</slot> to set up the contents of the custom element.一堆教程然后描述了如何使用<template>...</template><slot>...</slot>来设置自定义元素的内容。 You would then have to then include the template code in every HTML document in which you want to use the element rather than setting it up in the custom element class's constructor.然后,您必须将模板代码包含在要在其中使用该元素的每个 HTML 文档中,而不是在自定义元素类的构造函数中进行设置。 Doesn't this run counter to the fact that custom elements help simplify and encapsulate functionality in a way that makes them more portable?这与自定义元素有助于简化和封装功能以使其更具便携性的方式背道而驰吗? Or am I misunderstanding the proper usage and/or placement of the template within the document?还是我误解了模板在文档中的正确使用和/或放置?

Looking through SO, the closest I can find to addressing this is this question:通过 SO,我能找到的最接近解决这个问题的是这个问题:

How to stamp out template in self contained custom elements with vanilla js? 如何使用vanilla js在自包含的自定义元素中标记模板?

But the answer essentially sidesteps this all together and says "Don't use <template> ," and so doesn't really clear up my confusion.但是答案基本上回避了这一切并说“不要使用<template> ”,因此并没有真正消除我的困惑。

Actually <template> elements can be imported from another document via HTML Imports , along with the Javascript code that will define the custom element:实际上<template>元素可以通过HTML Imports从另一个文档 导入,以及定义自定义元素的 Javascript 代码:

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

So it doesn't need to be included in a every HTML document.所以它不需要包含在每个 HTML 文档中。 This post shows a minimal example.这篇文章展示了一个最小的例子。

HTML Imports are implemented only in Chrome and Opera. HTML 导入仅在 Chrome 和 Opera 中实现。 If you want to use them in the with Firefox and Safari you'll need to use the HTML Imports polyfill .如果你想在 Firefox 和 Safari 中使用它们,你需要使用HTML Imports polyfill

On the other hand and for the moment, Mozilla and Apple don't intend to implement HTML Imports natively in their respective browsers.另一方面,目前,Mozilla 和 Apple 不打算在各自的浏览器中本地实现 HTML 导入。 Therefore they recommend to define custom elements with pure Javascript modules (with import or <script src="..."> ), and promote template literals strings instead, which offer some advantages (variables, functions), but are sometimes more complicated to code in an IDE (because of their string representation).因此,他们建议使用纯 Javascript 模块(使用import<script src="..."> )定义自定义元素,并推广模板文字字符串,这提供了一些优势(变量、函数),但有时更复杂IDE 中的代码(因为它们的字符串表示)。

Maybe in the future standard HTML modules will be adopted by all browsers, and <template> will come back in the spotlight...也许将来所有浏览器都会采用标准的 HTML 模块,而<template>将重新成为人们关注的焦点……

Note that without HTML Imports you can still import yourself some HTML documents with fetch() :请注意,如果没有 HTML 导入,您仍然可以使用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
            }
        } )
    )

Update 2019 2019 年更新

HTML Imports won't be supported natively after Chrome 73 .在 Chrome 73 之后本机将不支持HTML 导入。 You should then use the other solutions listed above (the polyfill, an alternate module loader, JS import , or a direct download with fetch ).然后,您应该使用上面列出的其他解决方案(polyfill、备用模块加载器、JS import或使用fetch直接下载)。

Disclaimer: I'm an author of the rich-component library mentioned below.免责声明:我是下面提到的丰富组件库的作者。

After some time of experimenting with custom elements and recently raising a full blown project based solely upon them I'd like to share my insights on this:在对自定义元素进行了一段时间的试验并最近提出了一个完全基于它们的完整项目后,我想分享我对此的见解:

  • any component tiny as it is, is a candidate to grow to some beast任何微小的组件都可能成长为某种野兽
  • HTML part of it may grow to a point where it is very non-convenient to keep it within JS它的 HTML 部分可能会增长到将其保存在 JS 中非常不方便的程度
  • do use template, built and parsed once and from that point cloned and injected into the shadow root - this is the same best practice as to use document fragment instead of mutating a living DOM确实使用模板,构建和解析一次,从那时起克隆并注入影子根 - 这与使用文档片段而不是改变活动 DOM 的最佳实践相同
  • if the template contents should be changed from component's instance to instance - some kind of data binding framework may be used, and if minimalist approach on those is taken - it might still be easier and more performant to deal with a cloned-from-template document fragment than operate on string or template literals如果模板内容应该从组件的实例更改为实例 - 可能会使用某种数据绑定框架,并且如果对这些框架采取极简主义的方法 - 处理从模板克隆的文档可能仍然更容易和更高效片段而不是对字符串或模板文字进行操作

In order to not write the same dozens of lines over and over again I've prepared rich-component library, which:为了不一遍又一遍地写同样的几十行,我准备了丰富的组件库,其中:

  • normalizes some API for template provisioning and all those 'clone template, create shadow, inject template's content into it' lines of repeating code标准化一些用于模板配置的 API 以及所有那些“克隆模板、创建阴影、将模板的内容注入其中”的重复代码行
  • known to fetch html contents when html URL is provided已知在提供 html URL 时获取 html 内容
  • caches the templates so the fetch is done only once缓存模板,因此获取只完成一次

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM