Предотвращение применения нокаутом привязок к невидимым элементам

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

<div data-bind="visible: isEditable()">
    <textarea data-bind="kendoEditor: { value: name }" > </textarea>
    <button type="button" data-bind="click: toggleEdit(false)">Update</button>
</div>

Если вы посмотрите на следующий пример, он работает правильно. Вы можете нажать на элемент, он активирует редактор, вы можете нажать «Обновить», и изменения будут применены.

jsfiddle 1

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

jsfiddle 2

Есть ли способ предотвратить применение привязок к элементам, которые еще не видны?


person Carl    schedule 09.10.2015    source источник


Ответы (2)


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

Чтобы избежать привязки миллиона редакторов, вы можете просто менять местами шаблоны, а не иметь видимые и невидимые элементы:

<ul data-bind="template: { name: 'itemTmpl', foreach: Items }"></ul>
<script id="itemTmpl" type="text/html">
<li>
    <div data-bind="template: isEditable() ? 'editable' : 'notEditable'"></div>
    <ul data-bind="template: { name: 'itemTmpl', foreach: $data.items }"></ul>
</li>
</script>
<script id="notEditable" type="text/html">
    <span data-bind="html: name, click: toggleEdit.bind(null,true)">
    </span>
</script>
<script id="editable" type="text/html">
    <textarea data-bind="kendoEditor: { value: name }"></textarea>
    <button type="button" data-bind="click: toggleEdit.bind(null, false)">Update</button>
</script>

Обновленный скрипт

person Roy J    schedule 09.10.2015

Ответ Роя, вероятно, лучше, но да, есть способ предотвратить применение привязок к элементам-потомкам. Для этого вам нужна пользовательская привязка с init, которая возвращает:

return { controlsDescendantBindings: true };

Позже вы можете использовать

ko.applyBindingsToDescendants(bindingContext, element)

применять привязки.

Например вот так:

ko.bindingHandlers.myVisible = {
    init: function(element, valueAccessor) {
        var visible = ko.unwrap(valueAccessor());
      if (visible) {
        $(element).show();
        $(element).data('bindingsApplied', true);
      } else {
        $(element).hide();
        $(element).data('bindingsApplied', false);
        return { controlsDescendantBindings: true };
      }
    },
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var visible = ko.unwrap(valueAccessor());
        if (visible) {
            if (!$(element).data('bindingsApplied')) {
                ko.applyBindingsToDescendants(bindingContext, element);
                $(element).data('bindingsApplied', true);
            }
            $(element).show();
        } else {
            $(element).hide();
        }
    }
}

Скрипка

Документация

person Valyok26    schedule 09.10.2015