我目前正在尝试使用扩展程序在 Knockout JS 应用程序中实现自动保存功能。我想在用户停止在字段中输入时调用自动保存功能,而不仅仅是当他们退出时。
这是我想在更新可观察对象时调用的 logChange 方法。
//KO Extender for logging changes and calling the autosave function
ko.extenders.logChange = function (target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function (newValue) {
debugger;
var current = target(),
valueToWrite = newValue,
attName = precision;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
//self.autoSave(attName, target());
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({ notify: 'always' });
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
这就是我在我的 View 模型中设置可观察对象的方式。
self.controlCenter = ko.observable().extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" }, logChange: "ControlCenter" });
这是我对该可观察对象的 html 标记
<div class="pure-u-1-2 pure-u-md-1-4 pure-u-lg-1-8">
<label for="ddlControlCenter">Jurisdiction</label>
<input type="text" class="pure-input-1 full-text" list="controlCenterList" data-bind="textInput: controlCenter" />
<datalist id="controlCenterList" data-bind="foreach: controlCenters">
<option data-bind="value: $data"></option>
</datalist>
</div>
调用了 logChange 方法,但看起来并没有应用 rateLimit,因为在按键时会立即调用 logChange。
最佳答案
更新:
我已经更新了下面的 fiddle 。您犯的错误是您在更新新值后立即调用 logChange 函数内的函数。但 rateLimit 的概念是,可观察值已更改的通知在延迟后发送给所有订阅者。
换句话说,只有 observable 的订阅者会受到 rateLimit 的影响,而不会影响 logChange 函数中的任何内容。因此,正确的做法是在订阅者内部调用您的自动保存功能。
function ViewModel() {
var self = this;
self.autoSave = function(attName, value){
console.log(attName + " is now = " + value);
}
self.precision = ko.observable();
ko.extenders.logChange = function (target, precision) {
//create a writable computed observable to intercept writes to our observable
var result = ko.pureComputed({
read: target, //always return the original observables value
write: function (newValue) {
var current = target(),
valueToWrite = newValue;//,
self.precision(precision);
//attName = precision;
//only write if it changed
if (valueToWrite !== current) {
target(valueToWrite);
//self.autoSave(attName, target());
} else {
//if the rounded value is the same, but a different value was written, force a notification for the current field
if (newValue !== current) {
target.notifySubscribers(valueToWrite);
}
}
}
}).extend({ notify: 'always' });
//initialize with current value to make sure it is rounded appropriately
result(target());
//return the new computed observable
return result;
};
self.controlCenter = ko.observable().extend({ rateLimit: { timeout: 500, method: "notifyWhenChangesStop" }, logChange: "ControlCenter" });
self.controlCenters = ko.observableArray([]);
this.controlCenter.subscribe(function (val) {
if (val !== '')
this.controlCenters.push(val);
self.autoSave(self.precision(), val);
}, this);
}
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="pure-u-1-2 pure-u-md-1-4 pure-u-lg-1-8">
<label for="ddlControlCenter">Jurisdiction</label>
<input type="text" class="pure-input-1 full-text" list="controlCenterList" data-bind="textInput: controlCenter" />
<datalist id="controlCenterList" data-bind="foreach: controlCenters">
<option data-bind="value: $data"></option>
</datalist>
</div>
关于javascript - 超时后调用 Knockout JS Extender 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46474787/