Knockoutjs自定义绑定显示加载gif

时间:2012-11-22 15:41:29

标签: javascript knockout.js custom-binding

我正在尝试创建一个自定义绑定,在内容加载时显示加载gif。

ko.bindingHandlers.loader = {
    init: function (element) {
        $('<div>').addClass('loader').hide().appendTo($(element));
    },
    update: function (element, valueAccessor) {
        var isLoading = ko.utils.unwrapObservable(valueAccessor());
        var $element = $(element);
        var $children = $element.children(':not(.loader)');
        var $loader = $(element).find('.loader');

        if(isLoading) {
            $children.stop(true).css('visibility', 'hidden').attr('disabled', 'disabled');
            $loader.stop().fadeIn();
        } else {
            $loader.stop(true).fadeOut(function () {
                $children.css('visibility', 'visible').removeAttr('disabled');
            });
        }
    }
};

我可以在init中看到div.loader被附加到element,并且可以在isLoading更改为true时看到更新函数触发。但是一旦图像加载了(通过加载,我的意思是每个图像在它们各自的加载事件上返回一个已解决的承诺),一旦isLoading被设置回假,我看不到更新触发。

视图模型

function viewModel() {
    var self = this;

    self.movies = ko.observableArray([]);
    self.searchValue = ko.observable();
    self.isLoading = ko.observable(false);

    self.search = function () {
        self.isLoading = true;
        $.getJSON(arguments[0].action, { name: this.searchValue() }, function (data) {
            self.movies(data);
            $.when.apply($, promises).done(function() {
                setThumbnailHeight(function () {
                    self.isLoading = false;
                });
            });
        });
    }; 
    var setThumbnailHeight = function(callback) {
        var $items = $('.thumbnails li');
        var maxHeight = Math.max.apply(null, $items.map(function () {
            return $(this).innerHeight();
        }).get());
        $items.css('height', maxHeight);
        callback();
    };

}

ko.applyBindings(new viewModel());

setThumbnailHeight在正确的时间被召唤(一旦所有承诺都已解决)并且正常工作,我看到它将每个li的高度设置为最大高度并且可以看到回调(在这种情况下,function(){ self.isLoading = false; }被调用。

我的约束力

<ul class="content thumbnails" data-bind="foreach: movies, loader: $root.isLoading">
    <li class="movie">
        ...
    </li>
</ul>

所以回顾一下,问题是当isLoading设置为true时将显示加载gif,但是当它被设置回false时,它不会隐藏并显示新加载的内容。

1 个答案:

答案 0 :(得分:4)

所有可观察对象都是有效的,因此您无法使用=为其指定值。使用self.isLoading(true);代替self.isLoading = true;

self.search = function () {
    self.isLoading(true);
    $.getJSON(arguments[0].action, { name: this.searchValue() }, function (data) {
        self.movies(data);
        $.when.apply($, promises).done(function() {
            setThumbnailHeight(function () {
                self.isLoading(false);
            });
        });
    });
};

function(){ self.isLoading(false); }