Как шаблонизировать структуры If-Else в представлениях с привязкой к данным?


95

Я постоянно использую эту идиому в шаблонах HTML на основе KO:

<!-- ko if: isEdit -->
<td><input type="text" name="email" data-bind="value: email" /></td>
<!-- /ko -->
<!-- ko ifnot: isEdit -->
<td data-bind="text: email"></td>
<!-- /ko -->

Есть ли лучший / более чистый способ делать условные выражения в KO, или есть лучший подход, чем просто использование традиционных конструкций if-else?

Кроме того, я просто хотел бы отметить, что некоторые версии Internet Explorer (IE 8/9) неправильно анализируют приведенный выше пример. Пожалуйста, посмотрите этот вопрос SO для получения дополнительной информации. Краткое резюме: не используйте комментарии (виртуальные привязки) внутри тегов таблиц для поддержки IE. Используйте tbodyвместо этого:

<tbody data-bind="if: display"><tr><td>hello</td></tr></tbody>

Любой, кто смотрит на это, может захотеть
— Брайан М. Хант

Ответы:


64

Есть несколько способов обработки этого типа кода.

  • с комбинацией if / ifnot, как сейчас. Это отлично работает и не слишком многословно.

  • Связывание переключателя / регистра Майкла Беста ( https://github.com/mbest/knockout-switch-case ) довольно гибкое и может позволить вам легко справиться с этим и более сложными (больше состояний, чем true / false).

  • Другой вариант - использовать динамические шаблоны. Вы должны привязать область к одному или нескольким шаблонам с использованием имени шаблона на основе наблюдаемого. Вот сообщение, которое я написал на эту тему некоторое время назад: http://www.knockmeout.net/2011/03/quick-tip-dynamically-changing.html . В вашем сценарии это может выглядеть так:

<td data-bind="template: $root.getCellTemplate"></td>

<script id="cellEditTmpl" type="text/html">
    <input type="text" name="email" data-bind="value: email" />
</script>

<script id="cellTmpl" type="text/html">
    <span data-bind="text: email"></span>
</script>

getCellTemplateФункция может жить там , где, но будет дан элемент ($ данных) в качестве первого аргумента , и возвратит имя шаблона для использования.


странно, мой HTML не отображается. Также только что заметил, что Майкл дал примерно такой же ответ.
— RP Niemeyer

Спасибо за исчерпывающий список вариантов. Думаю, мой оригинальный стиль кода подходит для простых случаев. Я проверю другие варианты, когда возникнет необходимость.
— Jensen Ching

есть ли способ еще больше настроить шаблон, например "template: data, proppertyName: 'email'" и в шаблоне data-bind = "text: $ data [propertyName]".
— Онур Топал

@OnurTOPAL - да, если у вас есть переменная propertyName, вы можете динамически определять имя шаблона.
— RP Niemeyer

44

Один из подходов - использовать именованные шаблоны (которые могут поддерживать передачу аргументов):

<!-- ko template: isEdit() ? 'emailEdit' : 'emailDisplay' --><!-- /ko -->
<script id="emailEdit" type="text/html">
    <td><input type="text" name="email" data-bind="value: email" /></td>
</script>
<script id="emailDisplay" type="text/html">
    <td data-bind="text: email"></td>
</script>

Другой вариант - использовать мой плагин switch / case , который будет работать следующим образом:

<!-- ko switch -->
    <!-- ko case: isEdit -->
        <td><input type="text" name="email" data-bind="value: email" /></td>
    <!-- /ko -->
    <!-- ko case: $else -->
        <td data-bind="text: email"></td>
    <!-- /ko -->
<!-- /ko -->

Спасибо. Я буду помнить о плагине switch / case, когда в этом возникнет необходимость.
— Jensen Ching

2
Хороший плагин, который у вас есть! Обязательно воспользуюсь этим.
— Kukks

Именованные шаблоны отлично работают, и они поддерживают сценарии типа if elseif elseif else путем вложения терниарного оператора.

4

Чтобы избежать пересчета привязки нокаута при использовании комбинации if: / ifnot:, вы можете использовать их вместе с конструкцией with:

    <!-- ko with: $data.DoSomePerformanceCriticalWork($data.SomeParameter()) -->
        <!-- ko if: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
        <!-- ko ifnot: $data.Condition() -->
           ... some markup ...
        <!-- /ko -->
    <!-- /ko -->

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.