Логические операторы в условии {{#if}} Handlebars.js
Существует ли способ в Handlebars JS использовать логические операторы в стандартном условном операторе Handlebars.js? Например, что-то вроде этого:
{{#if section1 || section2}}
.. контент
{{/if}}
Я понимаю, что могу написать свой собственный хелпер, но сначала хотел бы убедиться, что не изобретаю колесо заново.
5 ответ(ов)
Это возможно с помощью "обмана" при использовании блочного помощника. Это, вероятно, противоречит идеологии людей, разработавших Handlebars.
Вот пример, как это можно реализовать:
Handlebars.registerHelper('ifCond', function(v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});
Затем вы можете использовать этот помощник в вашем шаблоне следующим образом:
{{#ifCond v1 v2}}
{{v1}} равен {{v2}}
{{else}}
{{v1}} не равен {{v2}}
{{/ifCond}}
Таким образом, вы сможете проверять условия внутри ваших шаблонов, что значительно увеличивает гибкость при работе с Handlebars.
В этой записи мы продолжаем работу с Handlebars, добавляя оператор сравнения в наш хелпер.
Вот пример кода, который регистрирует хелпер ifCond
, позволяющий использовать различные операции сравнения в шаблонах Handlebars:
Handlebars.registerHelper('ifCond', function (v1, operator, v2, options) {
switch (operator) {
case '==':
return (v1 == v2) ? options.fn(this) : options.inverse(this);
case '===':
return (v1 === v2) ? options.fn(this) : options.inverse(this);
case '!=':
return (v1 != v2) ? options.fn(this) : options.inverse(this);
case '!==':
return (v1 !== v2) ? options.fn(this) : options.inverse(this);
case '<':
return (v1 < v2) ? options.fn(this) : options.inverse(this);
case '<=':
return (v1 <= v2) ? options.fn(this) : options.inverse(this);
case '>':
return (v1 > v2) ? options.fn(this) : options.inverse(this);
case '>=':
return (v1 >= v2) ? options.fn(this) : options.inverse(this);
case '&&':
return (v1 && v2) ? options.fn(this) : options.inverse(this);
case '||':
return (v1 || v2) ? options.fn(this) : options.inverse(this);
default:
return options.inverse(this);
}
});
Вы можете использовать этот хелпер в шаблоне следующим образом:
{{#ifCond var1 '==' var2}}
Для тех, кто предпочитает CoffeeScript, вот аналогичный код:
Handlebars.registerHelper 'ifCond', (v1, operator, v2, options) ->
switch operator
when '==', '==='
return if v1 is v2 then options.fn this else options.inverse this
when '!=', '!=='
return if v1 != v2 then options.fn this else options.inverse this
when '<'
return if v1 < v2 then options.fn this else options.inverse this
when '<='
return if v1 <= v2 then options.fn this else options.inverse this
when '>'
return if v1 > v2 then options.fn this else options.inverse this
when '>='
return if v1 >= v2 then options.fn this else options.inverse this
when '&&', 'and'
return if v1 and v2 then options.fn this else options.inverse this
when '||', 'or'
return if v1 or v2 then options.fn this else options.inverse this
else
return options.inverse this
Таким образом, вы можете легко добавлять логику сравнения в свои шаблоны Handlebars, что сделает их более динамичными и гибкими.
Handlebars поддерживает вложенные операции, что предоставляет большую гибкость (и более чистый код), если мы немного иначе организуем нашу логику.
Например, можно использовать следующий код:
{{#if (or section1 section2)}}
.. контент
{{/if}}
На самом деле, можно добавить всевозможную логику:
{{#if (or
(eq section1 "foo")
(ne section2 "bar"))}}
.. контент
{{/if}}
Для этого нужно зарегистрировать следующие вспомогательные функции:
Handlebars.registerHelper({
eq: (v1, v2) => v1 === v2,
ne: (v1, v2) => v1 !== v2,
lt: (v1, v2) => v1 < v2,
gt: (v1, v2) => v1 > v2,
lte: (v1, v2) => v1 <= v2,
gte: (v1, v2) => v1 >= v2,
and() {
return Array.prototype.every.call(arguments, Boolean);
},
or() {
return Array.prototype.slice.call(arguments, 0, -1).some(Boolean);
}
});
Эти вспомогательные функции позволят вам создавать более сложные условия в ваших шаблонах Handlebars, что сделает ваш код более компактным и понятным.
Есть простой способ сделать это без написания вспомогательной функции... Все можно сделать прямо в шаблоне.
{{#if cond1}}
{{#if cond2}}
<div> и условие выполнено</div>
{{/if}}
{{else}}
<div> оба условия не были истинными</div>
{{/if}}
Редактирование: В свою очередь, вы можете использовать логическое "или", сделав это:
{{#if cond1}}
<div> или условие выполнено</div>
{{else}}
{{#if cond2}}
<div> или условие выполнено</div>
{{else}}
<div> ни одно из условий не было истинным</div>
{{/if}}
{{/if}}
Редактирование/Примечание: С сайта handlebarsjs.com: вот какие значения считаются "ложными":
Вы можете использовать вспомогательную функцию if для условного рендеринга блока. Если его аргумент возвращает false, undefined, null, "" или [] (ложное значение), тогда любое 'cond' (например, cond1 или cond2) не будет считаться истинным.
Вот улучшенное решение, которое работает с любым бинарным оператором (по крайней мере, с числами; строки могут работать не так хорошо с eval
, ОСТОРОЖНО С ВОЗМОЖНЫМ ВСТАВКОМ СКРИПТА, ЕСЛИ ИСПОЛЬЗУЕТСЯ ОПЕРАТОР, НЕ ОПРЕДЕЛЕННЫЙ С ПОЛЬЗОВАТЕЛЬСКИМИ ВВОДАМИ):
Handlebars.registerHelper("ifCond", function(v1, operator, v2, options) {
switch (operator) {
case "==":
return (v1 == v2) ? options.fn(this) : options.inverse(this);
case "!=":
return (v1 != v2) ? options.fn(this) : options.inverse(this);
case "===":
return (v1 === v2) ? options.fn(this) : options.inverse(this);
case "!==":
return (v1 !== v2) ? options.fn(this) : options.inverse(this);
case "&&":
return (v1 && v2) ? options.fn(this) : options.inverse(this);
case "||":
return (v1 || v2) ? options.fn(this) : options.inverse(this);
case "<":
return (v1 < v2) ? options.fn(this) : options.inverse(this);
case "<=":
return (v1 <= v2) ? options.fn(this) : options.inverse(this);
case ">":
return (v1 > v2) ? options.fn(this) : options.inverse(this);
case ">=":
return (v1 >= v2) ? options.fn(this) : options.inverse(this);
default:
// Используйте eval с осторожностью, особенно с пользовательским вводом
try {
const result = eval(`${v1} ${operator} ${v2}`);
return result ? options.fn(this) : options.inverse(this);
} catch (e) {
console.warn("Ошибка выполнения eval:", e);
return options.inverse(this);
}
}
});
Это решение предоставляет возможность использовать различные бинарные операторы в шаблонах Handlebars. Тем не менее, будьте осторожны с использованием eval
, особенно если вводят данными пользователи, поскольку это может привести к уязвимостям типа "вставка скриптов" (XSS). Лучше использовать заранее определенные операторы, чтобы избежать подобных рисков.
Как перенаправить на другую веб-страницу?
Где найти документацию по форматированию даты в JavaScript?
Как определить нажатие клавиши Esc?
Как проверить, содержит ли массив строку в TypeScript?
Ссылка и выполнение внешнего JavaScript-файла, размещенного на GitHub