2013-09-16 3 views
3

У меня есть модель нокаута, которая имеет несколько наблюдаемых свойств:Создание привязки обработчика Нокаут, который зависит от «дерева» наблюдаемых

var personViewModel = { 
    name: ko.observable('Bob'), 
    age: ko.observable(123) 
}; 

Я хотел бы создать пользовательские привязки, который делает вид лица модели. Однако я хотел бы, чтобы эта привязка обновлялась, если обновлены какие-либо дочерние свойства, то есть name или age.

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

В качестве обходного Я добавляю подписки на дочерние свойства в функции init:

ko.bindingHandlers.foo = { 
    init: function (element, valueAccessor, allBindingsAccessor, 
        viewModel, bindingContext) { 
     // setup code goes here ... DOM elements inserted etc.... 

     valueAccessor().age.subscribe(function() { 
      // Update the UI 
     }); 
     valueAccessor().name.subscribe(function() { 
      // Update the UI 
     }); 
    }, 
    update: function (element, valueAccessor, allBindingsAccessor, 
         viewModel, bindingContext) { 
     // Update the UI 
    } 
}; 

Примечание: это упрощенный пример, у меня есть общий подход к подписке на несколько дочерних наблюдаемыми!

Это хороший способ подойти к проблеме? Или есть какая-то встроенная функция нокаута, которую я пропускаю здесь?

ответ

4

ko.toJS будет Подвод зависимости, поэтому, если вы звоните это в обновлении будет решать все зависимости для вас

http://jsfiddle.net/rMG8y/

ko.bindingHandlers.foo = { 
    update: function(element, valueAccessor) { 
     //Resolve dependency 
     var dependency = ko.toJS(valueAccessor()); 

     //Do whatever 
     console.log(dependency); 
    } 
}; 
+0

Это на самом деле довольно умный ... –

+1

Удивительный - это работает (+1), но ... как это работает? Я понимаю, что делает 'toJS', но не почему это должно заставить привязку обновляться при изменении любого из значений? – ColinE

+1

Ну, он выполняет итерацию дерева объектов и разворачивает наблюдаемые, которые будут разрешать зависимости – Anders

0

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

http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html

Короче говоря, все обработчики привязки для данного элемента выполняются в контексте одного вычисленного наблюдаемого (в статье есть заметка о том, что это может измениться, так что каждый обработчик привязки работает в контексте его собственного вычисленного наблюдаемого - это произошло в версии 3.0). Зависимости нокаута воссоздаются каждый раз, когда оценивается функция в вычисленном наблюдаемом, поэтому вы должны каждый раз разворачивать наблюдаемые в обновлении, чтобы не потерять зависимость, как если бы вы только разворачивали наблюдаемое в init.

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

 var args = arguments; 
     ko.computed(function() 
     { 
      ko.utils.unwrapObservable(valueAccessor()/*or whatever observable you want to tie the update to*/); 
      doUpdateLogic(/*args or whatever you need*/); 
     }, this); 

Это, очевидно, опасно, так что используйте с осторожностью :)

Смежные вопросы