#javascript #lodash
#javascript #Lodash
Вопрос:
Мне очень нравится функция _.template, и я использую ее, чтобы позволить пользователю вводить переменные в свой текст, который я позже использую для замены некоторых данных.
Единственная проблема заключается в том, что мне нужно собрать все данные необязательных переменных перед вызовом скомпилированной функции шаблона, и этот процесс может занять некоторое время, которое в некоторых случаях может быть избыточным, поскольку пользователь не всегда будет использовать все необязательные переменные.
например, допустим, пользователь отправляет строку типа:
ZimGil is <%= age %> and his favorite language is <%= language %>
Мне нужно иметь age
language
переменные and, но мне не нужна phone
переменная, для получения которой требуется некоторое избыточное время.
Пытаюсь найти способ оценки асинхронных функций в шаблоне на основе используемых переменных
Ответ №1:
Вы можете использовать регулярное выражение для получения всех имен переменных.
Вам нужно следовать тому, что Lodash разрешает для переменных, чтобы получить их все. Смотрите комментарии рядом с каждой частью шаблона для объяснения.
TL; DR: регулярное выражение /<%[=|-]?(?:[s]|if|()*(. ?)(?:[s]|)|{)*%>/g
(без экранирования строки).
function getTemplateVariables(template) {
// making sure the template is a string
template = template || '';
const pattern = [
'<%[=|-]?', // look for opening tag (<%, <%=, or <%-)
'(?:[\s]|if|\()*', // accept any space after opening tag and before identifier
'(. ?)', // capture the variable name (`luigi` in <%= luigi %>)
'(?:[\s]|\)|\{)*', // accept any space after identifier and before closing tag
'%>' // look for closing tag
].join('');
const regex = new RegExp(pattern, 'g');
const matches = [];
let match;
while (match = regex.exec(template)) {
matches.push(match[1])
}
return _.uniq(matches);
}
_.uniq
используется для удаления повторяющихся переменных.
Изменение функции шаблона в Lodash
Вы можете переопределить функцию шаблона в Lodash с помощью mixin, а также возвращать переменные:
const originLodashTemplate = _.template;
_.mixin({
getTemplateVariables, // <-- you can use this on it's own
template: (...args) => { // <-- or together
const variables = _.getTemplateVariables(args[0]);
const template = originLodashTemplate (...args);
return {
variables,
template
};
}
});
Затем вы можете использовать его следующим образом:
const templateObj = _.template(
"ZimGil is <%= age %> and his favorite language is <%= language %>"
);
console.log(templateObj.variables);
// will print ["age","language"]
console.log(templateObj.template({ age: "over 5000 years old", language: "turtlese" }));
// will print 'ZimGil is over 5000 years old and his favorite language is turtlese'
Пример асинхронного
(async () => {
const templateObj = _.template(
"ZimGil is <%= age %> and his favorite language is <%= language %>"
);
const templateData = {};
for (const variable of templateObj.variables) {
const asyncResult = await mapToAsyncCall(variable);
templateData[variable] = asyncResu<
}
// this data will only contain existing variables
templateObj.template(templateData);
})();
Рабочий пример
Вот codepen с примером того, как все это работает.
УВЕДОМЛЕНИЕ
- Хотя я почти уверен, что переопределение
_.template
безопасно (не думаю, что оно используется с глобальным указателем изнутри Lodash), это может быть не так, и вы можете захотеть присвоить функции mixin другое имя! - Это не будет охватывать расширенную инъекцию кода, например
_.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
. вам нужно добавить слова, которые вы планируете разрешить, в регулярное выражение, чтобы поддерживать больше инъекций кода, которые распознают переменные. Прямо сейчас он охватывает толькоif
операторы, но в регулярное выражение «после открытия тега и до» выше можно добавить больше. Способ сделать это полностью (но это намного сложнее) — изменить исходный исходный код_.template
, чтобы фактически возвращать переменные и переопределять его новым кодом. Это будет поддерживать все инъекции кода, которые Lodash поддерживает из коробки.
Комментарии:
1.
console.log(templateObj.variables);
не работает.variables
является неизвестным ключом2. @Pian0_M4n Мне нужно больше информации, чтобы иметь возможность помочь 🙂 где вы пытались добавить журнал консоли? как вы использовали данные функции?