延迟Knockout的可见绑定?

时间:2014-08-21 16:31:36

标签: javascript knockout.js

我有一个购物车。当它为空时,我想显示一个带有“空”消息的div。当它有项目时,我想显示带有项目的div。目前,我有这样的事情......

<div style="display: none" data-bind="visible: items().length == 0">Empty</div>
<div style="display: none" data-bind="visible: items().length > 0">Not Empty</div>

......而这......

function ViewModel() {
    var self = this;

    self.items = ko.observableArray([]);
};

现在,我正在使用AJAX加载项目,这意味着如果购物车中是否有商品,则存在初始的不确定时期。这意味着页面首先显示“空”div,然后在看到有项目时快速替换它,将其替换为“非空”div-a进程,该进程在屏幕上看起来很笨重。

如何在我的AJAX完成之前暂停div上的visible函数并知道项目数?

我想到的一件事(看到工作here)是创建一个单独的属性showEmpty ...

<div style="display: none" data-bind="visible: showEmpty">Empty</div>
<div style="display: none" data-bind="visible: items().length > 0">Not Empty</div>

...并默认将其设置为undefined。这意味着visibleshowEmpty定义之前无法解决。然后我在AJAX调用中定义它......

self.items = ko.observableArray([]);
self.showEmpty = ko.observable(undefined);

// Fake AJAX
setTimeout(function() {
    self.items([1]);        
    self.showEmpty(self.items().length == 0);
}, 2000);

这100%有效但它提出了一个新问题:我现在手动更新一个observable。如下所示,当我想在数组中添加或删除项目时,这些函数现在必须担心更新showEmpty属性。

self.addItem = function() {
    self.items.push(1);
    self.showEmpty(false);
};

self.removeItem = function() {
    self.items.pop();
    self.showEmpty(self.items().length == 0);
};

我觉得KO的全部目的是避免这种事情。那么,我想要的是一些方法来设置 div的visible函数的分辨率的初始延迟。在初始等待之后,我希望visible函数根据可观察数​​组的.length进行更新。

谢谢!

3 个答案:

答案 0 :(得分:3)

@pquest在评论中给了我解决方案,所以我将其详细介绍给其他人稍后再看。

如我更新的fiddle所示,我添加了loadingDone观察点,并在visible绑定中添加了对它的引用...

<div style="display: none" data-bind="visible: items().length == 0 && loadingDone">Empty</div>
<div style="display: none" data-bind="visible: items().length > 0">Not Empty</div>

在我的脚本中,我能够删除所有手动更新...

function ViewModel() {
    var self = this;    

    self.items = ko.observableArray([]);
    self.loadingDone = ko.observable(false);

    // Fake AJAX
    setTimeout(function() {
        self.items([1]);        
        self.loadingDone(true);
    }, 2000);

    self.addItem = function() {
        self.items.push(1);
    };

    self.removeItem = function() {
        self.items.pop();
    };
};

尼斯!我仍然希望我能在不增加额外观察力的情况下完成同样的事情,但这比我所拥有的要好得多,所以我很高兴。

答案 1 :(得分:0)

(没有足够的回复评论,对不起)除非你绝对必须使用knockout来获取你的可见性,为什么不用jQuery而不是使用.show()和.hide()函数为你的AJAX工作。检查AJAX调用结束时的可观察项长度和.show()如果大于0,则保持隐藏状态..(除非你需要&#34;空&#34;消息)

答案 2 :(得分:0)

如果您不想添加observable,可以将viewTimeout移到viewModel之外,然后从那里调用ViewModel中的ajax函数。

var ViewModel = function() {
    // other code

    self.fake_ajax = function() {
    };
}

var vm = new ViewModel()
ko.applyBindings(vm);

setTimeout(function() {
    vm.fake_ajax();
}, 3000);

这是fiddle