JS/jQuery加载外部HTML模板渲染变量的实现方案
回答
这个需求完全可以实现。你最初写的示例代码存在几处基础错误:
- 你定义的
array是普通对象而非数组,无法直接调用forEach方法 - 浏览器环境没有原生同步的
load()方法用来加载外部文件,所有跨文件资源请求都需要走异步逻辑 - 模板字符串的插值替换需要在能访问到对应数据变量的作用域下执行,读取到外部模板的纯文本内容后不会自动完成变量绑定
你后续找到的fetch + eval拼接模板的方案虽然能实现基础效果,但存在严重的XSS安全隐患:如果外部模板内容被篡改,eval会直接执行模板里夹带的任意恶意JS代码,生产环境绝对不建议使用,另外你代码里写的Object.keys(arg).forEach循环没有任何实际作用,可以直接删除。
推荐实现方案
无依赖原生实现(安全优先,推荐)
不用eval,通过正则匹配占位符完成数据替换,同时做HTML转义从根源避免XSS风险:
文件代码
test.js
// 原变量命名为array实际是普通对象,改为语义化命名更易维护 const pageData = { title: 'hihihi', Name: 'hahaha' } async function renderExternalTemplate(templatePath, targetSelector, data) { // 异步加载外部模板文件 const templateRaw = await fetch(templatePath).then(res => res.text()) // 匹配模板中${arg.xxx}格式的占位符,完成替换和内容转义 const templateRendered = templateRaw.replace(/\$\{arg\.(\w+)\}/g, (match, propKey) => { const value = data[propKey] ?? '' // 转义特殊字符,防止XSS return String(value) .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, ''') }) // 将渲染完成的内容插入目标容器 document.querySelector(targetSelector).innerHTML = templateRendered } // 调用渲染方法 renderExternalTemplate('test.html', '#ok', pageData)
test.html(模板文件)
<div id="test">${arg.title}</div>
index.html
<div id="ok"></div>
jQuery 简化写法
如果项目已经引入jQuery,可以用它封装好的load()方法简化请求逻辑,同样不要用eval处理模板:
const pageData = {title: 'hihihi', Name: 'hahaha'} $('#ok').load('test.html', function(responseText) { const rendered = responseText.replace(/\$\{arg\.(\w+)\}/g, (match, propKey) => pageData[propKey] ?? '') $(this).html(rendered) })
注意事项
- 本地测试时不要直接双击HTML文件通过
file://协议打开,fetch请求会被浏览器跨域安全策略拦截,需要启动本地静态服务(比如VSCode的Live Server插件、node的http-server包)访问页面 - 如果需要渲染列表数据,只需要在拿到模板原始内容后循环数据项,逐条替换占位符后拼接成完整HTML,再统一插入容器即可
- 任何场景下都要避免用
eval处理外部加载的不可信内容,防止恶意代码执行
内容的提问来源于stack exchange,提问作者marilyn
相关产品推荐
相关产品推荐

