javascript - 超时后调用 Knockout JS Extender 函数

标签 javascript html knockout.js

我目前正在尝试使用扩展程序在 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/

相关文章:

html - 更改一个 li 菜单项的字体颜色

html - 溢出 :hidden dots and the end of a multiline text

javascript - 从可点击列表元素切换 DIV

javascript - 如何从对象渲染 Html 标签?

javascript - javascript 中的 "Top of Page"链接

java - 复选框元素的 Xpath 通过按值定位它在标签元素之后

javascript - knockout 绑定(bind)到日期选择器

javascript - 调用 $.each() 函数时上下文发生变化

javascript - Knockout.JS ,模板是通过表单没有添加任何数据

javascript - 查看未从指令功能更新