标签模板
标签模板其实不是模板,而是函数调用的一种特殊形式,模板字符串紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串,被称为“标签模板”
alert`123`
// 等同于
alert(123)
如果模板字符里面有变量 , 会将模板字符串先处理成多个参数,再调用函数 。
var a = 5;
var b = 10;
tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);
上面代码中,模板字符串前面有一个标识名tag
,它是一个函数。整个表达式的返回值,就是tag
函数处理模板字符串后的返回值。
函数tag
依次会接收到多个参数。
tag
函数的第一个参数是一个数组,该数组的成员是模板字符串中那些没有变量替换的部分
...values
是ES6新增写法后面会了解,在tag
函数中存的是标签模板中的参数
一个更复杂的例子。
passthru
函数采用rest参数的写法如下。
function passthru(literals, ...values) {
var output = "";
for (var index = 0; index < values.length; index++) {
output += literals[index] + values[index];
}
output += literals[index]
return output;
}
“标签模板”的一个重要应用,就是过滤HTML字符串,防止用户输入恶意内容。
var message =
SaferHTML`<p>${sender} has sent you a message.</p>`;
function SaferHTML(templateData) {
var s = templateData[0];
for (var i = 1; i < arguments.length; i++) {
var arg = String(arguments[i]);
// Escape special characters in the substitution.
s += arg.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
// Don't escape special characters in the template.
s += templateData[i];
}
return s;
}
上面代码中,sender
变量往往是用户提供的,经过SaferHTML
函数处理,里面的特殊字符都会被转义。
var sender = '<script>alert("abc")</script>'; // 恶意代码
var message = SaferHTML`<p>${sender} has sent you a message.</p>`;
message
// <p><script>alert("abc")</script> has sent you a message.</p>
防止恶意内容xss攻击的另一种方法,DOMPurify
DOMPurify – 针对 HTML、MathML 和 SVG 的仅支持DOM、快速、高容错的 XSS 过滤器
原代码:
<body>
<div class="container">
<form class="add-comment">
<textarea class="comment-text"></textarea>
<br>
<button class="btn btn-primary" value="submit">Post Comment</button>
</form>
<div class="comment"></div>
</div>
<script>
const addCommentForm = document.querySelector('.add-comment');
const textarea = document.querySelector('.comment-text');
const commentDiv = document.querySelector('.comment');
const user = '';
addCommentForm.addEventListener('submit', function (event) {
event.preventDefault(); //取消事件的默认动作
const newConmment = textarea.value.trim();
if (newConmment) {
commentDiv.innerHTML =
`
<div class=" comment-header">${user}</div>
<div class="comment-body">${textarea.value}</div>
`
textarea.value = ``;
}
})
</script>
</body>
引入purify.js
后代码
<body>
<div class="container">
<form class="add-comment">
<textarea class="comment-text"></textarea>
<br>
<button class="btn btn-primary" value="submit">Post Comment</button>
</form>
<div class="comment"></div>
</div>
<script src="https://cdn.bootcss.com/dompurify/1.0.3/purify.js"></script>
<script>
function sanitize(strings, ...values) {
const dirty = strings.reduce((prev, curr, i) => `${prev}${curr}${values[i] || ''}`, '');
return DOMPurify.sanitize(dirty);
}
const addCommentForm = document.querySelector('.add-comment');
const textarea = document.querySelector('.comment-text');
const commentDiv = document.querySelector('.comment');
const user = '';
addCommentForm.addEventListener('submit', function (event) {
event.preventDefault(); //取消事件的默认动作
const newConmment = textarea.value.trim();
if (newConmment) {
commentDiv.innerHTML = sanitize`
<div class=" comment-header">${user}</div>
<div class="comment-body">${textarea.value}</div>
`
textarea.value = ``;
}
})
</script>
</body>