标签模板字面量
该方法可以在字符串模板之前加入函数,用来处理模板:
function foo(str, ...val) {
console.log(str);
console.log(val);
}
var desc = "awesome";
foo`Everything is ${desc}!`;
// ["Everything is ", "!"]
// ["awesome"]
str为字符串数组,val为所有变量数组
该方法可以用来过滤HTML字符串,防止恶意攻击
let sender = '<script>alert("abc")</script>'; // 恶意代码
let message =
SaferHTML`<p>${sender} has sent you a message.</p>`;
function SaferHTML(templateData) {
let s = templateData[0];
for (let i = 1; i < arguments.length; i++) {
let 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;
}
// <p><script>alert("abc")</script> has sent you a message.</p>
sender为用户输入的变量,该方法可以过滤掉用户输入的HTML标签
实现国际化 参考
let I18n = {
use({locale, defaultCurrency, messageBundle}) {
I18n.locale = locale;
I18n.defaultCurrency = defaultCurrency;
I18n.messageBundle = messageBundle;
return I18n.translate;
},
translate(strings, ...values) {
let translationKey = I18n._buildKey(strings);
let translationString = I18n.messageBundle[translationKey];
if (translationString) {
let typeInfoForValues = strings.slice(1).map(I18n._extractTypeInfo);
let localizedValues = values.map((v, i) => I18n._localize(v, typeInfoForValues[i]));
return I18n._buildMessage(translationString, ...localizedValues);
}
return 'Error: translation missing!';
},
_localizers: {
s /*string*/: v => v.toLocaleString(I18n.locale),
c /*currency*/: (v, currency) => (
v.toLocaleString(I18n.locale, {
style: 'currency',
currency: currency || I18n.defaultCurrency
})
),
n /*number*/: (v, fractionalDigits) => (
v.toLocaleString(I18n.locale, {
minimumFractionDigits: fractionalDigits,
maximumFractionDigits: fractionalDigits
})
)
},
_extractTypeInfo(str) {
let match = typeInfoRegex.exec(str);
if (match) {
return {type: match[1], options: match[3]};
} else {
return {type: 's', options: ''};
}
},
_localize(value, {type, options}) {
return I18n._localizers[type](value, options);
},
// e.g. I18n._buildKey(['', ' has ', ':c in the']) == '{0} has {1} in the bank'
_buildKey(strings) {
let stripType = s => s.replace(typeInfoRegex, '');
let lastPartialKey = stripType(strings[strings.length - 1]);
let prependPartialKey = (memo, curr, i) => `${stripType(curr)}{${i}}${memo}`;
return strings.slice(0, -1).reduceRight(prependPartialKey, lastPartialKey);
},
// e.g. I18n._formatStrings('{0} {1}!', 'hello', 'world') == 'hello world!'
_buildMessage(str, ...values) {
return str.replace(/{(\d)}/g, (_, index) => values[Number(index)]);
}
};
let name = 'Bob';
let amount = 1234.56;
let i18n;
let messageBundle_fr = {
'Hello {0}, you have {1} in your bank account.': 'Bonjour {0}, vous avez {1} dans votre compte bancaire.'
};
let messageBundle_de = {
'Hello {0}, you have {1} in your bank account.': 'Hallo {0}, Sie haben {1} auf Ihrem Bankkonto'
};
let messageBundle_zh_Hant = {
'Hello {0}, you have {1} in your bank account.': '你好{0},你有{1}在您的銀行帳戶。'
};
i18n = I18n.use({locale: 'fr-CA', defaultCurrency: 'CAD', messageBundle: messageBundle_fr});
i18n`Hello ${name}, you have ${amount}:c in your bank account.`;
// => 'Bonjour Bob, vous avez 1 234,56 $CA dans votre compte bancaire.'
i18n = I18n.use({locale: 'de-DE', defaultCurrency: 'EUR', messageBundle: messageBundle_de});
i18n`Hello ${name}, you have ${amount}:c in your bank account.`;
// => 'Hallo Bob, Sie haben 1.234,56 € auf Ihrem Bankkonto.'
i18n = I18n.use({locale: 'zh-Hant-CN', defaultCurrency: 'CNY', messageBundle: messageBundle_zh_Hant});
i18n`Hello ${name}, you have ${amount}:c in your bank account.`;
// => '你好Bob,你有¥1,234.56在您的銀行帳戶。'
除此之外,你甚至可以使用标签模板,在 JavaScript 语言之中嵌入其他语言jsx具体实现
jsx`
<div>
<input
ref='input'
onChange='${this.handleChange}'
defaultValue='${this.state.value}' />
${this.state.value}
</div>
`
String.raw()
raw方法返回一个斜杠都会被在前面添加一个斜杠,用来转译字符串。如果原字符串已经被转译,则会再次转译。
String.raw`Hi\n${2+3}!`;
// 返回 "Hi\\n5!"
String.raw`Hi\u000A!`;
// 返回 "Hi\\u000A!"
String.raw`Hi\\n`
// 返回 "Hi\\\\n"