Обновление KnockoutJS Mapping неправильно работает с ‹!--ko foreach: --› привязка стиля

У меня есть шаблон KnockoutJS, который выглядит примерно так:

<div data-bind="template: {name: 'testTemplate', data: people}"></div>

<script id="testTemplate" type="text/html">
    <!--ko foreach: $data-->        
    <div class="items" data-bind="text: full() + ' updated at: ' + Date()"></div>
    <!--/ko-->
</script>

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

Я проиллюстрировал это, используя эти две скрипки:

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

Я действительно не могу понять, в чем разница. У меня сложилось впечатление, что привязка данных работает так же, как foreach, но позволяет больше контролировать объект внутри шаблона.

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

Разве <!--ko foreach:--> не должен соблюдать тот же шаблон, что и привязка шаблона foreach?


person farina    schedule 13.04.2012    source источник


Ответы (1)


Проблема в том, что ваша привязка шаблона создает подписку на ваш people observableArray, поскольку он передается как data. Когда массив people обновляется (элементы помещаются/удаляются и т. д.), это инициирует привязку шаблона для повторного рендеринга шаблона. В вашем случае это повторно отображает весь контент, поэтому foreach внутри шаблона никогда не будет эффективным.

Простой способ избежать этого — убедиться, что привязка шаблона не разворачивает ваш people observableArray. Вы можете передать данные, например { myArray: people }, а затем выполнить foreach на myArray.

Вот пример: http://jsfiddle.net/rniemeyer/bVPwM/4/

person RP Niemeyer    schedule 13.04.2012
comment
Теперь вы понимаете, что я просто пытаюсь придумать вопрос, на который вы не можете ответить :). Ха-ха... отличное решение! - person farina; 14.04.2012
comment
Я заметил, что то же самое происходит с ‹!-- ko if. Это по дизайну? - person farina; 17.04.2012
comment
if является оболочкой для привязки шаблона, поэтому да, поведение будет аналогичным. - person RP Niemeyer; 17.04.2012