检测对Knockout视图模型的更改

当然,这是一个非常容易回答的问题,但是有没有一种简单的方法来确定挖空视图模型的任何属性是否已经改变?

使用扩展程序:

ko.extenders.trackChange = function (target, track) { if (track) { target.isDirty = ko.observable(false); target.originalValue = target(); target.setOriginalValue = function(startingValue) { target.originalValue = startingValue; }; target.subscribe(function (newValue) { // use != not !== so numbers will equate naturally target.isDirty(newValue != target.originalValue); }); } return target; }; 

然后:

 self.MyProperty= ko.observable("Property Value").extend({ trackChange: true }); 

现在你可以这样检查:

 self.MyProperty.isDirty() 

您也可以编写一些通用的viewModel遍历来查看是否有任何改变:

  self.isDirty = ko.computed(function () { for (key in self) { if (self.hasOwnProperty(key) && ko.isObservable(self[key]) && typeof self[key].isDirty === 'function' && self[key].isDirty()) { return true; } } }); 

…然后在viewModel级别检查

 self.isDirty() 

您可以订阅要监视的属性:

 myViewModel.personName.subscribe(function(newValue) { alert("The person's new name is " + newValue); }); 

这将在personName更改时提醒。

好的,所以你想知道什么时候你的模型发生了变化…

 var viewModel = … // define your viewModel var changeLog = new Array(); function catchChanges(property, value){ changeLog.push({property: property, value: value}); viewModel.isDirty = true; } function initialiseViewModel() { // loop through all the properties in the model for (var property in viewModel) { if (viewModel.hasOwnProperty(property)) { // if they're observable if(viewModel[property].subscribe){ // subscribe to changes viewModel[property].subscribe(function(value) { catchChanges(property, value); }); } } } viewModel.isDirty = false; } function resetViewModel() { changeLog = new Array(); viewModel.isDirty = false; } 

(还没有testing过 – 但你应该明白)

考虑使用Knockout-Validation插件

它实现了以下内容:

yourProperty.isModified() – 检查用户是否修改了该值。

yourProperty.originalValue – 所以你可以检查值是否真的改变。

随着其他validation的东西,派上用场!

干杯

你可以使用下面的插件:

https://github.com/ZiadJ/knockoutjs-reactor

例如代码将允许您跟踪任何viewModel中的所有更改:

 ko.watch(someViewModel, { depth: -1 }, function(parents, child) { alert('New value is: ' + child()); }); 

PS:到目前为止,这将不能与嵌套在数组中的subscribable一起工作,但支持它的新版本正在开发中。

更新:示例代码已升级到v1.2b,它增加了对数组项和可订阅的可订阅属性的支持。

我有同样的问题,我需要观察viewModel的任何变化,以便将数据发送回服务器,如果任何人仍然intersted,我做了一些研究,这是最好的解决schemeiv'e设法组装:

 function GlobalObserver(viewModel, callback) { var self = this; viewModel.allChangesObserver = ko.computed(function() { self.viewModelRaw = ko.mapping.toJS(viewModel); }); viewModel.allChangesObserver.subscribe(function() { callback(self.viewModelRaw); }); self.dispose = function() { if (viewModel.allChangesObserver) viewModel.allChangesObserver.dispose(); delete viewModel.allChangesObserver; }; }; 

为了使用这个“全球观察者”:

 function updateEntireViewModel() { var rawViewModel = Ajax_GetItemEntity(); //fetch the json object.. //enter validation code here, to ensure entity is correct. if (koGlobalObserver) koGlobalObserver.dispose(); //If already observing the older ViewModel, stop doing that! var viewModel = ko.mapping.fromJS(rawViewModel); koGlobalObserver = new GlobalObserver(viewModel, Ajax_Submit); ko.applyBindings(viewModel [ ,optional dom element]); } 

请注意,给定的callback(在本例中为“Ajax_Submit”)将在视图模型上发生的任何更改上触发,所以我认为真的build议使用某种延迟机制来仅在用户完成编辑时发送实体属性:

 var _entitiesUpdateTimers = {}; function Ajax_Submit(entity) { var key = entity.ID; //or whatever uniquely related to the current view model.. if (typeof _entitiesUpdateTimers[key] !== 'undefined') clearTimeout(_entitiesUpdateTimers[key]); _entitiesUpdateTimers[key] = setTimeout(function() { SendEntityFunction(entity); }, 500); } 

我是JavaScript和knockout框架的新手(只有yestarday我开始使用这个奇妙的框架),所以如果我做错了,别生气。

希望这可以帮助!

我已经调整了@Brett Green代码并对其进行了扩展,以便我们可以接受AcceptChanges,将模型标记为不脏,并将模型标记为可追踪的。 这里是代码:

 var viewModel = { name: ko.observable() }; ko.track(viewModel); 

http://jsfiddle.net/david_freire/3HZEu/2/

我通过在页面加载时拍摄视图模型的快照,然后将该快照与当前视图模型进行比较来实现此目的。 我不在乎什么性质改变,只要有任何改变。

拍快照:

 var originalViewModel = JSON.stringify(ko.toJS(viewModel)); 

稍后再比较:

 if(originalViewModel != JSON.stringify(ko.toJS(viewModel))){ // Something has changed, but we don't know what } 

考虑一个视图模型如下

 function myViewModel(){ var that = this; that.Name = ko.observable(); that.OldState = ko.observable(); that.NewState = ko.observable(); that.dirtyCalcultions - ko.computed(function(){ // Code to execute when state of an observable changes. }); } 

绑定数据后,可以使用ko.toJS(myViewModel)函数来存储状态。

 myViewModel.Name("test"); myViewModel.OldState(ko.toJS(myViewModel)); 

你可以在你的视图模型中声明一个variables作为一个计算的观察值

 that.dirtyCalculations = ko.computed(function () {}); 

这个计算的函数将在视图模型中的任何其他可观察对象发生变化时进入。

那么你可以比较两个视图模型状态:

 that.dirtyCalculations = ko.computed(function () { that.NewState(that); //Compare old state to new state if(that.OldState().Name == that.NewState().Name()){ // View model states are same. } else{ // View model states are different. } 

});

**注意:这个计算的可观察函数也是在视图模型初始化时第一次执行的。 **

希望这可以帮助 ! 干杯!!