html5的template标签
template 是什么?
<template>
标签是特殊的一个标签,template里面的内容浏览器不会解析. 主要用于临时保存html代码.
如下代码,template里面的标签不会展示,JS,css都不会生效,不会出现语法错误.
例:
<template id="tpl">
<p>这里内容不会显示</p>
<img src="/logo.png" />
<style>
p{ font-size:16px;}
</style>
<script>
console.log("这段JS不会被执行")
</script>
</template>
打印出来看一下里面的结构是什么样的.
可以看来和普通标签有区别,多了一层 document-fragment
如何获取这个 document-fragment
呢?
template元素多出一个属性:
通过 content
属性就可以操作里面的内容了.
实操示例
一个模板示例:
<body>
<button id="load-tpl">加载模板</button>
<div id="app">
</div>
<template id="tpl">
<div id="container">
<h1>{{title}}</h1>
<div>
<p class="name">姓名:{{name}}</p>
<p class="age">年龄:{{age}}</p>
<p class="img"><img src="{{img}}" width="32" height="32" /></p>
<p>时间:{{time}}</p>
</div>
<div>
<button id="btn">提交</button>
</div>
</div>
<style>
.name{font-size:18px;color:red;}
.age{font-size: 14px;color:green;}
</style>
<script>
console.log("模板加载.")
</script>
<link rel="stylesheet" href="style.css">
<script src="index.js"></script>
</template>
<script>
function renderTpl(data){
const tpl=document.querySelector("#tpl");
/** content可以操作里面的dom节点 */
const fragment=tpl.content;
/** append节点被删除,所以这里使用clone */
const cloneFragment=fragment.cloneNode(true);
// 替换内容
let main=cloneFragment.querySelector("#container");
const reg = /{{(.*?)}}/g;
main.innerHTML=main.innerHTML.replace(reg,function(item,key){
return data[key] || "";
});
// 修改script内容
cloneFragment.querySelector("script").innerText=`
document.querySelector("#btn").addEventListener("click",function(){
console.log("提交")
});
console.log("加载:",${JSON.stringify(data)});
`
// 加载
const app=document.querySelector("#app");
app.appendChild(cloneFragment);
}
document.querySelector("#load-tpl")
.addEventListener("click",function(){
renderTpl({
"title":"个人信息",
"name":"张三",
"age":"18",
"img":"https://placehold.jp/48/999999/ff4400/128*128.png?text=%E5%BC%A0%E4%B8%89",
"time":(new Date).toLocaleTimeString()
});
})
</script>
</body>
上面示例,temaplte 是一个隐藏dom节点,图片,css,js都没有被执行,网络文件都没有被加载. 但可以像正常dom一样操作,修改js内容. 只有插入到文档中才被执行.
没有template之前,要实现就很复杂. 经常通过 <textarea style="display:none">
或 <script type="text/x-template" >
来存储大量html代码. 动态执行大量script,css也很麻烦. 如果嵌入script或textarea就会造成混乱.
- template的样式display默认中"none",可以设置为"block",但内容同样不显示.
- 动态执行JS,可以生成大量JS.
<body>
<!-- 代码预加 -->
<template id="tpl">
<script></script>
</template>
<!-- 执行代码 -->
<div id="runner"></div>
<textarea id="code" placeholder="编写JS代码" cols="50" rows="5"></textarea>
<p><button id="run-btn" type="button">执行代码</button></p>
<script>
document.querySelector("#run-btn").addEventListener("click",function(){
let code =document.querySelector("#code").value;
const tpl=document.querySelector("#tpl").content;
const clone=document.importNode(tpl,true);
const script=clone.querySelector("script");
script.innerHTML=code;
const runner=document.querySelector("#runner");
runner.innerHTML="";
runner.appendChild(clone);
})
</script>
</body>
效果:
同理,可以生成html,css.
上一篇,html转dom节点
<!-- 代码预加 -->
<template id="tpl"></template>
<textarea id="code" placeholder="编写html代码" cols="50" rows="5"></textarea>
<p><button id="run-btn" type="button">执行代码</button></p>
<hr/>
<!-- 执行代码 -->
<div id="runner"></div>
<script>
document.querySelector("#run-btn").addEventListener("click",function(){
let code =document.querySelector("#code").value;
const tpl=document.querySelector("#tpl");
const clone=document.importNode(tpl,true);
clone.innerHTML=code;
const runner=document.querySelector("#runner");
runner.innerHTML="";
runner.appendChild(clone.content);
})
</script>
注意: 处于安全考虑,浏览器innerHTML方式不执行script脚本.
不能动态创建script. 只能通过document.createElement('script')
创建再执行.
用新标签替换旧标签.
newJS=document.createElement("script");
newJS.innerHTML=oldJS.innerHTML;
if(oldJS.src){
newJS.setAttribute("src",oldJS.src);
}
frag.replaceChild(newJS,oldJS)
注意: 别想着直接克隆,克隆也不能生效. 必须新建一个.
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<!-- 代码预加 -->
<template id="tpl"></template>
<textarea id="code" placeholder="编写html代码" cols="50" rows="5"></textarea>
<p><button id="run-btn" type="button">执行代码</button></p>
<hr/>
<!-- 执行代码 -->
<div id="runner"></div>
<script>
document.querySelector("#run-btn").addEventListener("click",function(){
let code =document.querySelector("#code").value;
const tpl=document.querySelector("#tpl");
const clone=document.importNode(tpl,true);
clone.innerHTML=code;
const frag=clone.content;
// 重新替换JS标签
const scripts=frag.querySelectorAll("script");
scripts.forEach(function(oldJS){
let newJS=document.createElement("script");
newJS.innerHTML=oldJS.innerHTML;
if(oldJS.src){
newJS.setAttribute("src",oldJS.src);
}
frag.replaceChild(newJS,oldJS)
})
const runner=document.querySelector("#runner");
runner.innerHTML="";
runner.appendChild(frag);
})
</script>
</body>
</html>
结果:
原作者:阿金
本文地址:https://hi-arkin.com/archives/html-template.html