【问题标题】:How to pause notifications of an observableArray?如何暂停 observableArray 的通知?
【发布时间】:2017-12-13 01:54:40
【问题描述】:

场景:

我正在创建一个基于 knockout.js 的长时间运行的 Web 应用程序,我需要为我的视图模型加载数倍不同的数据。

为了提高性能并避免不必要的更新,我需要在更新我的视图模型期间暂时避免我的可观察对象和可观察数组的正常依赖跟踪链。 新数据加载完成后,就可以安全恢复正常的ko依赖跟踪了。

为了暂停 observables,我使用了 RP NiemeyerwithPausing 函数,这里描述了:Change observable but don't notify subscribers in knockout.js

有什么方法可以暂时忽略 observablearray 中的删除和插入?

【问题讨论】:

    标签: knockout.js


    【解决方案1】:

    pauseableComputed 和 observable withPausing 实现的启发,我创建了 pauseableObservablepauseableObservableArray,它们能够停止向订阅者发送通知,然后在需要时恢复。它还对所有嵌套的可暂停属性递归地工作。

    你可以玩HERE on Codepen

    PauseableObservable:

    // PauseableObservable - it's observable that have functions to 'pause' and 'resume' notifications to subscribers (pause/resume work recursive for all pauseable child).
    
    ko.isPauseableObservable = function(instance) {
        return ko.isObservable(instance) && instance.hasOwnProperty("pause");
    }
    
    ko.pauseableObservable = function(value) {
        var that = ko.observable(value);
    
        function getPauseableChildren() {
            var currentValue = that();
            var properties = Object.getOwnPropertyNames(currentValue);
            var pauseables = properties.filter((property) => {
                return ko.isPauseableObservable(currentValue[property]);
            });
            return pauseables.map((property) => { 
                return currentValue[property]; 
            });
        }
    
        that.pauseNotifications = false;
        that.isDirty = false;
    
        that.notifySubscribers = function() {
            if (!that.pauseNotifications) {
                ko.subscribable.fn.notifySubscribers.apply(that, arguments);
            }
            that.isDirty = that.pauseNotifications;
        };
    
        that.pause = function() {    
            that.pauseNotifications = true;
            var pauseableChildren = getPauseableChildren();
            pauseableChildren.forEach((child) => { child.pause(); });
        }
    
        that.resume = function() {    
            that.pauseNotifications = false;
    
            if (that.isDirty) {
                that.valueHasMutated();
            }
    
            var pauseableChildren = getPauseableChildren();
            pauseableChildren.forEach((child)=> { child.resume(); });
        }
    
        return that;
    }
    

    PauseableObservableArray

    // PauseableObservableArray - it's observable array that have functions to 'pause' and 'resume' notifications to subscribers about add/remove items. 
    // In case if array items pauseable observables - run recursively run 'pause'/'resume' on them.
    
    ko.pauseableObservableArray = function(items) {
        var that = ko.observableArray(items);
    
        that.pauseNotifications = false;
        that.isDirty = false;
        that.lastNotification = [];
    
        that.notifySubscribers = function() {
            if (!that.pauseNotifications) {
                ko.subscribable.fn.notifySubscribers.apply(that, arguments);
            } else {
                that.lastNotification = arguments;
            }
            that.isDirty = that.pauseNotifications;
        };
    
        that.pause = function () {
            var items = that();
            that.pauseNotifications = true;
            items.forEach(function(item) {
                if(ko.isPauseableObservable(item)) {
                    item.pause();
                }
            });
        }
    
        that.resume = function () {
            var items = that();
            that.pauseNotifications = false;
    
            if(that.isDirty) {
                ko.subscribable.fn.notifySubscribers.apply(that, that.lastArguments);
            } 
            items.forEach(function(item) {
                if(ko.isPauseableObservable(item)) {
                    item.resume();
                }
            });
        }
    
        that.refresh = function () {
            that.resume();
            that.pause();
        }
    
        return that;
    }
    

    用法示例:

    var firstItem = ko.pauseableObservable("Hello");
    var secondItem = ko.pauseableObservable("World");
    var items = [
        firstItem,
        secondItem
    ];
    var array = ko.pauseableObservable(items);
    
    // Stop notifications from specific observable
    firstItem.pause();
    // Change won't raise notification to subscribers
    firstItem("Hi");
    // Resume notifications
    firstItem.resume();
    
    // Stop notifications from all items of array
    array.pause();
    // Change won't raise notification to subscribers
    array.push("Hey");
    array()[0]("Hi");
    // Resume notifications
    array.resume();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-26
      • 1970-01-01
      相关资源
      最近更新 更多