ES6学习之— 字符串扩展(二)

标签模板

标签模板其实不是模板,而是函数调用的一种特殊形式,模板字符串紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串,被称为“标签模板”

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, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");

    // 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>&lt;script&gt;alert("abc")&lt;/script&gt; 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>
posted @ 2019-10-18 17:16  Bradleyu  阅读(185)  评论(0编辑  收藏  举报