Можете ли вы вызвать ko.applyBindings, чтобы связать частичное представление?

258

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

HTML-код для содержимого диалога извлекается с использованием AJAX, поэтому я хочу иметь возможность вызова ko.applyBindingsпосле завершения запроса, и я хочу привязать модель дочернего представления только к той части HTML-кода, которая загружается через ajax внутри диалогового элемента div.

Это действительно возможно, или мне нужно загрузить ВСЕ мои представления и модели просмотра, когда страница первоначально загружается, а затем вызывать ko.applyBindingsодин раз?

Чарли
источник

Ответы:

431

ko.applyBindings принимает второй параметр, который является элементом DOM для использования в качестве корневого.

Это позволит вам сделать что-то вроде:

<div id="one">
  <input data-bind="value: name" />
</div>

<div id="two">
  <input data-bind="value: name" />
</div>

<script type="text/javascript">
  var viewModelA = {
     name: ko.observable("Bob")
  };

  var viewModelB = {
     name: ko.observable("Ted")
  };

  ko.applyBindings(viewModelA, document.getElementById("one"));
  ko.applyBindings(viewModelB, document.getElementById("two"));
</script>

Таким образом, вы можете использовать эту технику для привязки viewModel к динамическому контенту, который вы загружаете в свой диалог. В целом, вы просто должны быть осторожны, чтобы не вызывать applyBindingsнесколько раз одни и те же элементы, так как вы получите несколько обработчиков событий.

Р.П. Нимейер
источник
17
Если вы также хотите удалить привязки в какой-то момент в будущем, вы можете позвонить либо ko.cleanNode(document.getElementById("one")для очистки, либо ko.removeNode(document.getElementById("one")для очистки и удаления узла из DOM.
Майкл Беркомпас
7
Просто обратите внимание, что cleanNodeи removeNodeне удалит обработчики событий, поэтому будьте осторожны. В некоторых случаях предпочтительно использовать templateили withпривязку к этим областям, поэтому у вас есть новые визуализированные элементы.
RP Niemeyer
7
Это то, чего не хватает в нокауте. Мы не намерены специально «перепривязывать» разделы. Однако KO прикрепляет события, используя jQuery, если на него есть ссылка, так что вы можете $(element).unbind();удалить все обработчики.
RP Niemeyer
5
Где документированы эти функции (applyBindings, cleanNode, removeNode)? Я не могу найти сигнатуры их функций на knockoutjs.com.
EricP
2
Было бы хорошо, если бы это было где-то легко найти в документации. Я даже не видел упоминания об этом.
Трэвис Кауфман
61

Хотя ответ Нимейер является более правильным ответом на этот вопрос, вы могли бы также сделать следующее:

<div>
  <input data-bind="value: VMA.name" />
</div>

<div>
  <input data-bind="value: VMB.name" />
</div>

<script type="text/javascript">
  var viewModels = {
     VMA: {name: ko.observable("Bob")},
     VMB: {name: ko.observable("Ted")}
  };

  ko.applyBindings(viewModels);
</script>

Это означает, что вам не нужно указывать элемент DOM, и вы даже можете привязать несколько моделей к одному элементу, например так:

<div>
  <input data-bind="value: VMA.name() + ' and ' + VMB.name()" />
</div>
MHU
источник
4
Вы также можете использовать «с» для выделения областей страницы отдельным моделям - data-bind = «with: VMA»
lexicalscope
3
@flamingpenguin: Да, но withне дешево, смотрите: ссылка
mhu
7

Мне удалось связать пользовательскую модель с элементом во время выполнения. Код здесь: http://jsfiddle.net/ZiglioNZ/tzD4T/457/

Интересно, что я применяю атрибут data-bind к элементу, который не определил:

    var handle = slider.slider().find(".ui-slider-handle").first();
    $(handle).attr("data-bind", "tooltip: viewModel.value");
    ko.applyBindings(viewModel.value, $(handle)[0]);
ZiglioUK
источник
возникли проблемы с Ko 2.3, приведенный выше код находится в обработчике клиента, который вызывается, когда я применяю глобальный ko.applyBindings (). Так что теперь я получаю ошибку «Вы не можете применять привязки несколько раз к одному и тому же элементу». Я все еще пытаюсь понять, почему я получаю ошибку. Разве мы не можем применить привязку к одной и той же переменной несколько раз, каждый к разным элементам?
ZiglioUK
Вот версия с 2.3, которая не работает: jsfiddle.net/ZiglioNZ/tzD4T/458
ZiglioUK
Добавление вызова к ko.cleanNode () перед вызовом applyBinding к частичному представлению, похоже, не помогает: jsfiddle.net/ZiglioNZ/tzD4T/459
ZiglioUK
Решено: мне даже не нужно было вызывать applyBindings!
ZiglioUK
Я только что отредактировал исходный код knockoutjs и прокомментировал часть, в которой функция выдает «Вы не можете применять привязки несколько раз к одному и тому же элементу.», теперь все работает хорошо ... я знаю, что это грязное решение, но я плохо знаком с библиотекой, поэтому я не знаю, как не применять его несколько раз для моей проблемы.
Geomorillo