超时后调用Knockout JS Extender函数

时间:2017-09-28 17:10:17

标签: javascript html knockout.js

我目前正在尝试使用扩展程序在Knockout JS应用程序中实现自动保存功能。当用户停止在字段中输入时,我想调用自动保存功能,而不仅仅是当他们选中它时。

这是我想在observable更新时调用的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;

};

这就是我在viewmodel中设置observable的方法。

    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,因为在keypress上立即调用logChange。

1 个答案:

答案 0 :(得分:1)

更新

我已经更新了下面的小提琴。您犯的错误是您在更新新值后立即在logChange函数内调用函数。但是rateLimit的概念是,在延迟到所有订阅者之后发送了可观察值被更改的通知

换句话说,只有observable的订阅者受rateLimit的影响,而不是logChange函数中的任何内容。因此,正确的方法是在订阅者中调用autoSave函数。

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>