您现在的位置是:网站首页 > <template>-内容模板文章详情

<template>-内容模板

<template> 是 HTML5 引入的一个特殊标签,用于声明可重复使用的 HTML 片段。它不会直接渲染到页面上,而是作为 JavaScript 操作的“模板仓库”,通过脚本动态实例化内容。

<template> 的基本特性

<template> 标签内的内容默认具有以下行为:

  1. 惰性加载:内容不会在页面加载时立即渲染
  2. 隔离性:模板内的脚本不会执行,图片不会加载
  3. DOM 访问:需要通过 JavaScript 提取内容
<template id="user-card">
  <div class="card">
    <h3 class="username"></h3>
    <p class="bio"></p>
  </div>
</template>

与普通 HTML 的区别

普通 HTML 元素会立即成为 DOM 的一部分,而 <template> 的内容保持“ inert ”状态:

<!-- 这个 div 会立即显示 -->
<div id="visible">立即显示的内容</div>

<!-- 这个 template 需要手动激活 -->
<template id="hidden-template">
  <div>不会自动显示的内容</div>
</template>

实际应用场景

动态内容生成

最常见的用法是配合 JavaScript 动态生成重复结构:

const template = document.getElementById('user-card');
const users = [
  { name: '张三', bio: '前端工程师' },
  { name: '李四', bio: 'UI设计师' }
];

users.forEach(user => {
  const instance = template.content.cloneNode(true);
  instance.querySelector('.username').textContent = user.name;
  instance.querySelector('.bio').textContent = user.bio;
  document.body.appendChild(instance);
});

配合 Web Components

在自定义元素中使用模板可以提升性能:

class MyElement extends HTMLElement {
  constructor() {
    super();
    const template = document.getElementById('my-element-template');
    const shadowRoot = this.attachShadow({ mode: 'open' });
    shadowRoot.appendChild(template.content.cloneNode(true));
  }
}

customElements.define('my-element', MyElement);

高级用法

嵌套模板

模板可以多层嵌套实现复杂结构:

<template id="page-template">
  <header>
    <template id="header-content"></template>
  </header>
  <main>
    <template id="main-content"></template>
  </main>
</template>

条件模板

结合 JavaScript 实现条件渲染:

function renderTemplate(condition) {
  const template = condition 
    ? document.getElementById('template-a')
    : document.getElementById('template-b');
    
  return template.content.cloneNode(true);
}

浏览器兼容性处理

虽然现代浏览器都支持 <template>,但需要兼容旧浏览器时可以这样处理:

if ('content' in document.createElement('template')) {
  // 使用模板
} else {
  // 降级方案
  const div = document.createElement('div');
  div.style.display = 'none';
  // ...其他降级逻辑
}

性能优化技巧

  1. 批量操作:在文档片段中完成所有 DOM 操作后再插入
  2. 预编译:提前克隆模板内容备用
  3. 缓存查询:避免重复查询模板元素
// 性能优化示例
const cachedTemplate = document.getElementById('my-template').content;

function renderItems(items) {
  const fragment = document.createDocumentFragment();
  
  items.forEach(item => {
    const instance = cachedTemplate.cloneNode(true);
    // ...填充数据
    fragment.appendChild(instance);
  });
  
  document.getElementById('container').appendChild(fragment);
}

与其他技术的对比

与字符串模板对比

// 字符串拼接方式
function createCard(user) {
  return `
    <div class="card">
      <h3>${user.name}</h3>
      <p>${user.bio}</p>
    </div>
  `;
}

// 模板标签方式
const template = document.getElementById('card-template');
function createCard(user) {
  const clone = template.content.cloneNode(true);
  clone.querySelector('h3').textContent = user.name;
  clone.querySelector('p').textContent = user.bio;
  return clone;
}

与 JSX 对比

React 的 JSX 最终也会编译为类似模板的结构:

// JSX
const Card = ({ user }) => (
  <div className="card">
    <h3>{user.name}</h3>
    <p>{user.bio}</p>
  </div>
);

// 等效的模板用法
<template id="card-template">
  <div class="card">
    <h3></h3>
    <p></p>
  </div>
</template>

实际项目中的最佳实践

  1. 模板组织:按功能模块拆分模板文件
  2. 版本控制:模板与 JavaScript 逻辑同步更新
  3. 文档注释:为模板添加使用说明
<!-- 
  用户卡片模板
  使用方式:
  1. 克隆模板内容
  2. 设置 .username 和 .bio 元素内容
  3. 添加到DOM
-->
<template id="user-card">
  <!-- 模板内容 -->
</template>

常见问题解决方案

事件绑定问题

模板克隆后需要重新绑定事件:

template.content.querySelector('button').addEventListener('click', handler); // 无效

const clone = template.content.cloneNode(true);
clone.querySelector('button').addEventListener('click', handler); // 有效

样式隔离方案

使用 Shadow DOM 实现样式隔离:

const template = document.getElementById('styled-template');
const host = document.getElementById('host');
const shadow = host.attachShadow({ mode: 'open' });
shadow.appendChild(template.content.cloneNode(true));

模板的扩展用法

服务端渲染配合

在服务端生成模板内容:

// Node.js 环境
const template = `
  <template id="server-template">
    <div>服务端生成的模板</div>
  </template>
`;
res.send(template);

与构建工具集成

Webpack 等工具可以自动处理模板文件:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.html$/,
        include: /templates/,
        use: 'html-loader'
      }
    ]
  }
}

模板的生命周期管理

  1. 创建阶段:定义模板结构
  2. 激活阶段:克隆并插入DOM
  3. 更新阶段:修改已实例化的模板
  4. 销毁阶段:移除模板实例
// 生命周期管理示例
class TemplateManager {
  constructor(templateId) {
    this.template = document.getElementById(templateId);
    this.instances = new Set();
  }
  
  createInstance(data) {
    const clone = this.template.content.cloneNode(true);
    // ...填充数据
    this.instances.add(clone);
    return clone;
  }
  
  removeInstance(instance) {
    instance.parentNode?.removeChild(instance);
    this.instances.delete(instance);
  }
}

模板的调试技巧

  1. 在开发者工具中查看 #document-fragment
  2. 使用 console.dir(template.content) 查看结构
  3. 添加临时ID辅助调试:
<template id="debug-template">
  <div data-debug-id="template-container">
    <!-- 内容 -->
  </div>
</template>

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步