KnockoutJS подписаться на изменения свойств с помощью плагина Mapping
Есть ли в любом случае я могу сказать плагину knockout mapping подписаться на все изменения свойств, вызывающие определенную функцию?
Я понимаю, что могу вручную подписаться на событие изменения свойств следующим образом:
var viewModel = {
name: ko.observable('foo'),
}
// subscribe manually here
viewModel.name.subscribe(function(newValue){
// do work
})
Я хотел бы иметь возможность общей подписки, хотя, поскольку мои модели представления могут отличаться, я не хочу жестко кодировать имена свойств. Я создал функцию, которая делает это, но это может быть не лучшим подходом. Он работает во всех браузерах, кроме IE7 и под.
Здесь я беру viewmodel в качестве аргумента и пытаюсь размышлять о нем, подписываясь на свойства:
function subscribeToKO(data) {
$.each(data, function (property, value) {
if (getType(value) == "Object")
data[property] = subscribeToKO(value);
else if (getType(value) == "Array") {
$.each(value, function (index, item) {
item = subscribeToKO(item);
});
}
else {
if (value.subscribe) {
value.subscribe(function (newValue) {
// do work
});
}
}
});
return data;
}
Как я уже сказал, это работает, но так как я использую подключение отображения, я надеялся, что есть крюк, который я мог бы использовать, чтобы предоставить ему функцию, которая будет в общем подписываться на изменения свойств.
Что-то вроде:
mapping = {
create: function(options){
options.data.subscribe(function(newValue){
// do work ???
});
}
}
ko.mapping.fromJS(viewModel, mapping);
Есть идеи?
2 ответа:
Вот общий подход, основанный нагрязном флаге Райана Нимейера .
Нажмите здесь для JsFiddle .Html:
<ol> <li> Telephone : <input data-bind="value: telephone"/> </li> <li> Address : <input data-bind="value: address"/> </li> </ol>
Javascript:
var model = { telephone: ko.observable('0294658963'), address: ko.observable('167 New Crest Rd') }; // knockout extension for creating a changed flag (similar to Ryan's dirty flag except it resets itself after every change) ko.changedFlag = function(root) { var result = function() {}; var initialState = ko.observable(ko.toJSON(root)); result.isChanged = ko.dependentObservable(function() { var changed = initialState() !== ko.toJSON(root); if (changed) result.reset(); return changed; }); result.reset = function() { initialState(ko.toJSON(root)); }; return result; }; // add changed flag property to the model model.changedFlag = new ko.changedFlag(model); // subscribe to changes model.changedFlag.isChanged.subscribe(function(isChanged) { if (isChanged) alert("model changed"); }); ko.applyBindings(model);
Этот удобный маленький плагин довольно близок к тому, что вы сделали, но он поставляется с несколькими вариантами и может работать над гораздо более широким набором требований, не требуя плагина отображения:
Https://github.com/ZiadJ/knockoutjs-reactor
В основном это позволяет писать такой код:
ko.watch(viewModel, function(target, trigger) { // do work });