基于JavaScript渲染原生HTML模板:如何优雅填充模板内容?
优雅填充HTML模板的几种方案
针对你提出的模板填充需求,我分享两种实用方案,既避开逐个querySelector的繁琐,又能保证灵活性和安全性:
方案1:直接替换占位符字符串(快速适配你的双下划线模板)
如果想直接沿用你现有的双下划线占位符模板,可以通过字符串正则替换的方式快速实现,步骤如下:
- 获取模板内容并转为字符串
- 用正则匹配所有
__xxx__格式的占位符,替换为对应数据 - 将替换后的字符串转为DOM元素
代码示例:
// 获取模板 const template = document.querySelector('template'); // 克隆模板内容(避免修改原模板) const clone = template.content.cloneNode(true); // 把克隆内容转为字符串 let templateHtml = clone.innerHTML; // 待填充数据(保留你原有的双下划线格式) const data = { __heading__: 'Lots of things', __label1__: 'label 1', __value1__: 'value 1', __label2__: 'label 2', __value2__: 'value 2', __instruction__: 'Do the thing', __label3__: 'label 3', __value3__: 'value 3', }; // 正则替换所有占位符,没有对应数据则保留原占位符 templateHtml = templateHtml.replace(/__(\w+)__/g, (match, key) => { return data[`__${key}__`] || match; }); // 将替换后的HTML转回DOM元素 const parser = new DOMParser(); const renderedElement = parser.parseFromString(templateHtml, 'text/html').body.firstChild; // 把渲染好的元素添加到页面 document.body.appendChild(renderedElement);
⚠️ 注意:这种方法如果数据包含未过滤的HTML内容,会有XSS风险,只适合可信数据源的场景。
方案2:自定义属性标记(更安全、可维护的优雅方案)
如果你愿意调整模板格式,推荐用自定义属性标记需要填充的元素和属性,这种方式更灵活,也能避免XSS问题,容错性更高:
修改后的模板:
<template id="my-template"> <div> <h2 data-template-key="heading"></h2> <label data-template-key="label1"></label> <input type="text" data-template-key="value1" data-template-attr="value"> <label data-template-key="label2"></label> <input type="text" data-template-key="value2" data-template-attr="value"> <div data-template-key="instruction"></div> <label data-template-key="label3"></label> <input type="text" data-template-key="value3" data-template-attr="value"> </div> </template>
data-template-key:标记该元素对应的数据键名data-template-attr:可选,标记要填充的是元素的属性(比如input的value),默认填充textContent
对应的简化数据:
const data = { heading: 'Lots of things', label1: 'label 1', value1: 'value 1', label2: 'label 2', value2: 'value 2', instruction: 'Do the thing', label3: 'label 3', value3: 'value 3', };
通用渲染函数:
function renderTemplate(templateId, data) { const template = document.getElementById(templateId); const clone = template.content.cloneNode(true); // 遍历所有带标记的元素 clone.querySelectorAll('[data-template-key]').forEach(element => { const key = element.dataset.templateKey; const value = data[key]; if (!value) return; // 没有对应数据则跳过 // 判断是填充文本内容还是属性 const attr = element.dataset.templateAttr; if (attr) { element.setAttribute(attr, value); } else { element.textContent = value; } }); return clone.firstElementChild; } // 调用渲染并添加到页面 const rendered = renderTemplate('my-template', data); document.body.appendChild(rendered);
这种方案的优势:
- 无需依赖固定的元素顺序或标签类型,结构变动也不影响渲染
- 用
textContent和setAttribute避免XSS注入,安全性更高 - 代码可复用,后续新增模板或数据字段只需对应添加标记即可
内容的提问来源于stack exchange,提问作者run_the_race
相关产品推荐
相关产品推荐

