Handlebars.js: {{#switch}} помощник

Созданный на 22 дек. 2014  ·  15Комментарии  ·  Источник: handlebars-lang/handlebars.js

Это очень полезно, и я думаю, было бы лучше, если бы он был встроен в библиотеку:

{{#switch state}}
    {{#case "page1" "page2"}}toolbar{{/case}}
    {{#case "page1" break=true}}page1{{/case}}
    {{#case "page2" break=true}}page2{{/case}}
    {{#case "page3" break=true}}page3{{/case}}
    {{#default}}page0{{/default}}
{{/switch}}

Самый полезный комментарий

Эта страница в настоящее время является 3-м результатом поиска Google по запросу "Помощник переключателя руля". Для удобства людей, прибывающих сюда из поисковой системы, вот реализация Криса Монтруа, которая поддерживает однозначные предложения case такие как {{#case "page1"}} :

Handlebars.registerHelper("switch", function(value, options) {
    this._switch_value_ = value;
    var html = options.fn(this); // Process the body of the switch block
    delete this._switch_value_;
    return html;
});

Handlebars.registerHelper("case", function(value, options) {
    if (value == this._switch_value_) {
        return options.fn(this);
    }
});

Вот улучшенный помощник case который поддерживает предложения с переменным числом значений, например {{#case "page1" "page2"}} :

Handlebars.registerHelper("case", function() {
    // Convert "arguments" to a real array - stackoverflow.com/a/4775938
    var args = Array.prototype.slice.call(arguments);

    var options    = args.pop();
    var caseValues = args;

    if (caseValues.indexOf(this._switch_value_) === -1) {
        return '';
    } else {
        return options.fn(this);
    }
});

Все 15 Комментарий

Это то, чего можно достичь (хакерским способом) с помощью стандартных помощников. Мы хотим, чтобы встроенные помощники были относительно легкими, вместо того, чтобы позволить третьим сторонам реализовывать нужные им помощники наиболее подходящим для них способом, используя вспомогательный API.

Эта страница в настоящее время является 3-м результатом поиска Google по запросу "Помощник переключателя руля". Для удобства людей, прибывающих сюда из поисковой системы, вот реализация Криса Монтруа, которая поддерживает однозначные предложения case такие как {{#case "page1"}} :

Handlebars.registerHelper("switch", function(value, options) {
    this._switch_value_ = value;
    var html = options.fn(this); // Process the body of the switch block
    delete this._switch_value_;
    return html;
});

Handlebars.registerHelper("case", function(value, options) {
    if (value == this._switch_value_) {
        return options.fn(this);
    }
});

Вот улучшенный помощник case который поддерживает предложения с переменным числом значений, например {{#case "page1" "page2"}} :

Handlebars.registerHelper("case", function() {
    // Convert "arguments" to a real array - stackoverflow.com/a/4775938
    var args = Array.prototype.slice.call(arguments);

    var options    = args.pop();
    var caseValues = args;

    if (caseValues.indexOf(this._switch_value_) === -1) {
        return '';
    } else {
        return options.fn(this);
    }
});

Очень красиво, коротко и мило. Раньше я встречал гораздо более длинные.

Можно добавить пару вещей: {{#default}} {{/default}} и {{#case "value" break=true}} .

@stevenvachon По запросу;)

module.exports = {
    switch: function(value, options) {
        this._switch_value_ = value;
        this._switch_break_ = false;
        var html = options.fn(this);
        delete this._switch_break_;
        delete this._switch_value_;
        return html;
    },
    case: function(value, options) {
        var args = Array.prototype.slice.call(arguments);
        var options    = args.pop();
        var caseValues = args;

        if (this._switch_break_ || caseValues.indexOf(this._switch_value_) === -1) {
            return '';
        } else {
            if (options.hash.break === true) {
                this._switch_break_ = true;
            }
            return options.fn(this);
        }
    },
    default: function(options) {
        if (!this._switch_break_) {
            return options.fn(this);
        }
    }
};

@ Билли: Где мы должны это включить?

@jimkoul Это вспомогательные функции, поэтому все зависит от ваших настроек.

Моя настройка (с Gulp + gulp-hb) поддерживает указание шаблона glob для файлов js, которые экспортируют вспомогательные функции, как указано выше, поэтому это выглядит так:

// ...
.pipe(handlebars({
  helpers: 'handlebars/helpers/*.js'
})
// ...

Если вы все еще не уверены, проведите небольшое исследование того, как вспомогательные функции работают с рулями и как их реализовать с любой реализацией ручек, которые вы используете.

Было бы неплохо, если бы мы могли передавать переменную через имя переключателя и не писать полные {{assign}} через каждое. Таким образом, опция становится значением переменной.

Кроме того, я также получаю сообщение undefined, даже если переменная изменяется правильно, когда дело выполнено.

Это то, что у меня есть для помощника

"use strict";
Handlebars.registerHelper("switch", function(value, options) {
    this._switch_value_ = value;
    this._switch_break_ = false;
    var html = options.fn(this);
    delete this._switch_break_;
    delete this._switch_value_;
    return html;
});

Handlebars.registerHelper("case", function(value, options) {
    var args = Array.prototype.slice.call(arguments);
    var options    = args.pop();
    var caseValues = args;

    if (this._switch_break_ || caseValues.indexOf(this._switch_value_) === -1) {
        return '';
    } else {
        if (options.hash.break === true) {
            this._switch_break_ = true;
        }
        return options.fn(this);
    }
});

Handlebars.registerHelper("default", function(options) {
    if (!this._switch_break_) {
        return options.fn(this);
    }
});

Вот что у меня в файле hbs:

{{#assign "testParam"}}foo{{/assign}}
{{#switch testParam}}
    {{#case "boo"}}{{#assign "testParam"}}case1 has been met{{/assign}}{{/case}}
    {{#case "foo" break=true}}{{#assign "testParam"}}case2 has been met{{/assign}}{{/case}}
    {{#case "tried" break=true}}{{#assign "testParam"}}case3 has been met{{/assign}}{{/case}}
    {{#case "bwahahaha" break=true}}{{#assign "testParam"}}case4 has been met{{/assign}}{{/case}}
    {{#default break=true}}{{#assign "testParam"}}nothing matched{{/assign}}{{/default}}
{{/switch}}

{{#ttpartial "testSwitch.content"}}
        {{testParam}}
{{/ttpartial}}

или по какой-то причине вышеупомянутое значение по умолчанию всегда имеет приоритет, даже если выполняется один из указанных выше случаев.

Вот что я использую:

Handlebars.registerHelper('switch', function(name, value, options) {
    this['_switch_value_' + name] = value;
    this['_switch_break_' + name] = false;
    var html = options.fn(this);
    delete this['_switch_break_' + name];
    delete this['_switch_value_' + name];
    return html;
});
Handlebars.registerHelper('case', function(name, value, options) {
    var args = Array.prototype.slice.call(arguments);
    var options    = args.pop();
    var caseValues = args;

    if ( this['_switch_break_' + name] || caseValues.indexOf(this['_switch_value_' + name]) === -1) {
        return '';
    } else {
        this['_switch_break_' + name] = true;
        return options.fn(this);
    }
});
Handlebars.registerHelper('default', function(name, options) {
    if ( !this['_switch_break_' + name] ) {
        return options.fn(this);
    }
});

Переключатели названы, поэтому их можно разветвлять (имбрикация? Не уверен в слове ...)
Кроме того, перерыв всегда выполняется при выполнении условия.

то есть:

    {{#switch "1" "aaa"}}
        {{#case "1" "aaa"}}
            {{#switch "2" "bbb"}}
                {{#case "2" "bbb"}}ok{{/case}}
            {{/switch}}
        {{/case}}
        {{#default "1"}}nok{{/default}}
    {{/switch}}

Я уверен, что не понимаю, как это работает, поэтому прошу прощения за недоразумение, но ... Возможно ли, чтобы переключатель работал в пределах each ? Пробовал, но все время получаю ошибки.

Вот что у меня есть:

{{#each columns}}
    {{#switch this}}
        {{#case 'foo'}}
        {{/case}}
        {{#case 'bar'}}
        {{/case}}
    {{/switch}}
{{/each}}

Но я получаю следующее:

Uncaught TypeError: Cannot create property '_switch_value_' on string 'name'

Мне кажется, что this должно быть чем-то отличным от ожидаемого, но я точно не знаю.

Похоже, мне удалось заставить его работать, изменив switch следующим образом:

Handlebars.registerHelper({
    switch: function(value, options) {
        return options.fn({
            _switch_value_: value,
            _switch_break_: false
        });
    },
    //...
});

Но я предполагаю, что теряю что-то по другим делам. При этом я всегда мог привязать эти значения к options , и я думаю, что это сработает.

@ Билли-@ a-le?

@infinityplusone, к сожалению, я не использовал рули должным образом в течение многих лет, поэтому я полагаю, что реализация помощника, возможно, сильно изменилась с тех пор, как я это написал, и, вероятно, поэтому он не работал так, как ожидалось. Я не уверен, извините, что разочаровал.

@infinityplusone Если вы используете мою версию, вам нужно "назвать" переключатель.
Итак, с вашим примером:

{{#each columns}}
    {{#switch "myswitch" this}}
        {{#case "myswitch" 'foo'}}
        {{/case}}
        {{#case "myswitch" 'bar'}}
        {{/case}}
    {{/switch}}
{{/each}}

для вложенного блока переключателей

Handlebars.__switch_stack__ = [];

Handlebars.registerHelper( "switch", function( value, options ) {
    Handlebars.__switch_stack__.push({
        switch_match : false,
        switch_value : value
    });
    var html = options.fn( this );
    Handlebars.__switch_stack__.pop();
    return html;
} );
Handlebars.registerHelper( "case", function( value, options ) {
    var args = Array.from( arguments );
    var options = args.pop();
    var caseValues = args;
    var stack = Handlebars.__switch_stack__[Handlebars.__switch_stack__.length - 1];

    if ( stack.switch_match || caseValues.indexOf( stack.switch_value ) === -1 ) {
        return '';
    } else {
        stack.switch_match = true;
        return options.fn( this );
    }
} );
Handlebars.registerHelper( "default", function( options ) {
    var stack = Handlebars.__switch_stack__[Handlebars.__switch_stack__.length - 1];
    if ( !stack.switch_match ) {
        return options.fn( this );
    }
} );
{{#switch state}}
    {{#case "page1" "page2"}}page 1 or 2{{/case}}
    {{#case "page3"}}page3{{/case}}
    {{#case "page4"}}page4{{/case}}
    {{#case "page5"}}
            {{#switch s}}
                {{#case "3"}}s = 3{{/case}}
                {{#case "2"}}s = 2{{/case}}
                {{#case "1"}}s = 1{{/case}}
                {{#default}}unknown{{/default}}
            {{/switch}}
    {{/case}}
    {{#default}}page0{{/default}}
{{/switch}}
var data = {
    state : 'page5',
    s : '1'
};

var html = template( data );

Как насчет этого?
просто если вы хотите преобразовать ключ в значение.

javascript
module.exports = функция (ввод, случаи, значения) {
const caseArray = case.split (',')
константа valueArray = values.split (',')
const index = caseArray.indexOf (ввод)

возвращаемое значениеArray [индекс]
};
руль
{{переключатель "Д" "ДА, НЕТ, Д", "ДА, НЕТ, УДАЛЕН"}}
`` ''

Была ли эта страница полезной?
0 / 5 - 0 рейтинги