探索HTML中的 <template> 标签

今天我们来聊一聊HTML中一个较少被提及的标签:<template>。虽然它在页面加载时不可见,但在现代Web框架中却扮演着重要的角色,比如Vue、Svelte和Solid等。

我们先介绍一下 <template> 标签的使用。

<template>:内容模板元素

内容模板<template>)元素是一种用于保存客户端内容机制,该内容在加载页面时不会呈现,但随后可以在运行时使用 JavaScript 实例化。

将模板视为一个可存储在文档中以便后续使用的内容片段。虽然解析器在加载页面时确实会处理 <template> 元素的内容,但这样做只是为了确保这些内容有效;但元素内容不会被渲染。

关键点

  1. <template> 元素可以简单地理解为将多个元素组合在一起的一个组件。
  2. 它不会显示在页面上,只能通过JS去实例化。

属性

在深入了解 <template> 属性之前,我们先来了解一个重要的接口:DocumentFragment

DocumentFragment

DocumentFragment,文档片段接口,表示一个没有父对象的最小文档对象。

它被作为一个轻量版的 Document 使用,就像标准的 document 一样,存储由节点(nodes)组成的文档结构。与 document 相比,最大的区别是它不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染,且不会对性能产生影响。

它的 API 和 document 是差不多类似的,包括 appendquerySelector ...

而我们会用到里面的 cloneNode 方法。用于返回节点的一个副本。

cloneNode 支持一个 deep 参数,用于是否采用深度克隆,如果为 true,则该节点的所有后代节点也都会被克隆,如果为 false,则只克隆该节点本身。

content 属性

<template> 支持的唯一一个属性 content 是一个只读的 DocumentFragment,包含了模板所表示的DOM树。

使用

现在,我们再来看一下如何去使用 <template>

index.html

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>待办事项列表</title>
  </head>
  <body>
    <h1>我的待办事项</h1>
    <input type="text" id="newTodo" placeholder="添加新的待办事项" />
    <ul id="todoList"></ul>

    <!-- 模板定义 -->
    <template id="todoTemplate">
      <li class="todo-item">
        <span></span>
        <button onclick="this.parentNode.remove()">完成</button>
      </li>
    </template>

    <script src="./index.js"></script>
  </body>
</html>

index.js

jsx 复制代码
const newTodoInput = document.getElementById('newTodo')
const todoList = document.getElementById('todoList')
const todoTemplate = document.getElementById('todoTemplate').content

const addTodo = todoText => {
  // 克隆模板内容
  // const clone = todoTemplate.cloneNode(true)
  const clone = document.importNode(todoTemplate, true)
  const todoSpan = clone.querySelector('span')
  todoSpan.textContent = todoText

  todoList.appendChild(clone)
}

newTodoInput.addEventListener('keypress', function (event) {
  if (event.key === 'Enter') {
    const todoText = this.value.trim()
    if (todoText) {
      addTodo(todoText)
      this.value = ''
    }
  }
})

addTodo('写文章')

在这个例子中,我们通过 cloneNode 克隆模板并修改里面的值,实现了添加待办事项的功能。

这里,我们并没有直接去操作 <template> 本身的内容,而是复制了一份;如果直接操作模板的话,会导致模板数据错乱,影响后续其他使用该模板的操作。

同时,这里实际上又两种复制模板的方式:

  • document.importNode(todoTemplate, true)
  • todoTemplate.cloneNode(true)

实现的效果都是一样的,只是 cloneNode 是 Node 接口所提供的一个 API,而 importNode 是 Document 实现的一个 API。

官方案例中推荐使用的是:importNode

添加 <style>

当然,也可以在 <template> 添加 <style> 标签来使用样式。或者说可以添加各种各样的标签,但是要注意其使用。

这里还是以刚刚那个案例,添加一个 <style>

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <body>
    <template id="todoTemplate">
	    <!-- 新增 -->
      <style>
        .todo-item > span {
          color: red;
        }
      </style>
      <li class="todo-item">
        <span></span>
        <button onclick="this.parentNode.remove()">完成</button>
      </li>
    </template>
  </body>
</html>

最终效果,实际上把 style 标签也添加进来了,所以这里要注意样式冲突的问题。

<slot> ?

有的人可能会想到利用 <slot> 去做处理,不需要单独去查询指定的元素了,但是 <slot> 的话,需要配合 Web Component 才能进行使用。

当然,也可以通过 <slot>name 属性去查找位置,进行数据的插入,也可以,虽然这里面有着千丝万缕的关系,但是有点违背了使用的性质。

<slot> 主要就是用于配合 Web Component,然后再通过标签在 html 上进行使用的,而 <template> 是只能通过 js 实例化再利用 DOM 添加到 页面上的。

结论

<template> 标签是一个强大的工具,它允许开发者在不渲染的情况下预定义HTML结构,并在需要时通过JavaScript动态实例化。

前面也提到了 <template>,在框架内部是很常见的,像在 Vue、Svelte、Solid 等等框架都使用到了该技术;同时这里也是做个铺垫,为后面讲解 Solid 的组件编译提前做一下准备 ^_^。

参考链接

  1. template:内容模板元素 - HTML(超文本标记语言) | MDN (mozilla.org)
  2. DocumentFragment - Web API | MDN (mozilla.org)
相关推荐
Senar17 分钟前
Web端选择本地文件的几种方式
前端·javascript·html
烛阴35 分钟前
UV Coordinates & Uniforms -- OpenGL UV坐标和Uniform变量
前端·webgl
姑苏洛言39 分钟前
扫码小程序实现仓库进销存管理中遇到的问题 setStorageSync 存储大小限制错误解决方案
前端·后端
烛阴1 小时前
JavaScript 的 8 大“阴间陷阱”,你绝对踩过!99% 程序员崩溃瞬间
前端·javascript·面试
lh_12541 小时前
ECharts 地图开发入门
前端·javascript·echarts
jjw_zyfx1 小时前
成熟的前端vue vite websocket,Django后端实现方案包含主动断开websocket连接的实现
前端·vue.js·websocket
Mikey_n2 小时前
前台调用接口的方式及速率对比
前端
周之鸥2 小时前
使用 Electron 打包可执行文件和资源:完整实战教程
前端·javascript·electron
我爱吃朱肉2 小时前
HTMLCSS模板实现水滴动画效果
前端·css·css3
机器视觉知识推荐、就业指导2 小时前
开源QML控件:进度条滑动控件(含源码下载链接)
前端·qt·开源·qml