Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/428.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 当可观察对象发生变化时,敲除绑定不会更新_Javascript_Knockout.js - Fatal编程技术网

Javascript 当可观察对象发生变化时,敲除绑定不会更新

Javascript 当可观察对象发生变化时,敲除绑定不会更新,javascript,knockout.js,Javascript,Knockout.js,我有一个下拉按钮,它应该在ajax请求完成后可用 <div class="form-input"> <label class="">Sort by:</label> <select name="orderby" class="selectpicker" data-bind="value: sortBy, optionsCaption: 'Default', disable: waiting"> <option valu

我有一个下拉按钮,它应该在ajax请求完成后可用

<div class="form-input">
   <label class="">Sort by:</label>
   <select name="orderby" class="selectpicker" data-bind="value: sortBy, optionsCaption: 'Default', disable: waiting">
      <option value="some_value">some_option</option>
      <option value="some_value">some_option</option>
   </select>
</div>

嗯,在一个页面上,它显示所有文章,但下拉按钮仍然被阻止,我不知道这到底是什么问题。

我建议对您的viewmodel进行一些更改,通过订阅自动加载

我认为您总是希望在加载后将
waiting
设置为false,这与请求是否成功无关。还可以考虑低级请求错误,您需要为这些错误添加一个处理程序

function ArticleViewModel() {
    var self = this;

    self.articles = ko.observableArray();

    self.pageSize = ko.observable();
    self.sortBy = ko.observable('asc');
    self.currentPage = ko.observable();
    self.waiting = ko.observable(true);
    self.viewTemplate = ko.observable();

    // API
    self.setCardView = function() {
        self.viewTemplate('cardview-template');
        self.pageSize(12);
        self.currentPage(1);
    };
    self.setListView = function() {
        self.viewTemplate('listview-template');
        self.pageSize(4);
        self.currentPage(1);
    };

    // compute Ajax-relevant parameters
    self.ajaxParams = ko.pureComputed(function () {
        return {
            page: self.currentPage(),
            size: self.pageSize(),
            sortby: self.sortBy()
        };
    }).extend({ rateLimit: { timeout: 10, method: 'notifyWhenChangesStop' } });

    // auto-load when params change
    self.ajaxParams.subscribe(function (params) {
        self.waiting(true);
        api.ajax.get(api.urls.article.getArticles, params, function (response) {
            if (response.success) {
                self.articles(response.data.items);
            }
            self.waiting(false);
        });
    });

    // set inital view (also triggers load)
    self.setListView();
}

$(function() {
    var vm = new ArticleViewModel();
    ko.applyBindings(vm, $('#article-plugin')[0]);
});
更严格地说,我建议您不要将
true
false
作为“加载”指示器。从技术上讲,可能有多个Ajax请求正在运行,这将是一种竞争条件。返回的第一个请求重置“加载”状态,下一个请求仍然覆盖viewmodel数据。使用计数器,或者在有挂起的请求时阻止新请求

rateLimit
扩展程序确保参数的快速连续更改(如调用
setListView()
时发生的更改)不会导致多个Ajax请求


如果您的Ajax请求是由jQuery内部完成的,我建议使用以下设置来使用
done
fail
始终
承诺处理程序:

function ApiWrapper() {
    var self = this;

    function unwrapApiResponse(response) {
        if (response.success) {
            return new $.Deferred().resolve(response.data).promise();
        } else {
            return new $.Deferred().reject(response.error).promise();
        }
    }

    self.getArticles = function (params) {
        return $.get('articleUrl', params).then(unwrapApiResponse);
    };
    // more functions like this
}

var api = new ApiWrapper();
在您的viewmodel中:

self.ajaxParams.subscribe(function (params) {
    self.waiting(true);
    api.getArticles(params).done(function (data) {
        self.articles(data.items);
    }).fail(function (err) {
        // show error
    }).always(function () {
        self.waiting(false);
    });
});

我建议您对viewmodel进行一些更改,通过订阅自动加载

我认为您总是希望在加载后将
waiting
设置为false,这与请求是否成功无关。还可以考虑低级请求错误,您需要为这些错误添加一个处理程序

function ArticleViewModel() {
    var self = this;

    self.articles = ko.observableArray();

    self.pageSize = ko.observable();
    self.sortBy = ko.observable('asc');
    self.currentPage = ko.observable();
    self.waiting = ko.observable(true);
    self.viewTemplate = ko.observable();

    // API
    self.setCardView = function() {
        self.viewTemplate('cardview-template');
        self.pageSize(12);
        self.currentPage(1);
    };
    self.setListView = function() {
        self.viewTemplate('listview-template');
        self.pageSize(4);
        self.currentPage(1);
    };

    // compute Ajax-relevant parameters
    self.ajaxParams = ko.pureComputed(function () {
        return {
            page: self.currentPage(),
            size: self.pageSize(),
            sortby: self.sortBy()
        };
    }).extend({ rateLimit: { timeout: 10, method: 'notifyWhenChangesStop' } });

    // auto-load when params change
    self.ajaxParams.subscribe(function (params) {
        self.waiting(true);
        api.ajax.get(api.urls.article.getArticles, params, function (response) {
            if (response.success) {
                self.articles(response.data.items);
            }
            self.waiting(false);
        });
    });

    // set inital view (also triggers load)
    self.setListView();
}

$(function() {
    var vm = new ArticleViewModel();
    ko.applyBindings(vm, $('#article-plugin')[0]);
});
更严格地说,我建议您不要将
true
false
作为“加载”指示器。从技术上讲,可能有多个Ajax请求正在运行,这将是一种竞争条件。返回的第一个请求重置“加载”状态,下一个请求仍然覆盖viewmodel数据。使用计数器,或者在有挂起的请求时阻止新请求

rateLimit
扩展程序确保参数的快速连续更改(如调用
setListView()
时发生的更改)不会导致多个Ajax请求


如果您的Ajax请求是由jQuery内部完成的,我建议使用以下设置来使用
done
fail
始终
承诺处理程序:

function ApiWrapper() {
    var self = this;

    function unwrapApiResponse(response) {
        if (response.success) {
            return new $.Deferred().resolve(response.data).promise();
        } else {
            return new $.Deferred().reject(response.error).promise();
        }
    }

    self.getArticles = function (params) {
        return $.get('articleUrl', params).then(unwrapApiResponse);
    };
    // more functions like this
}

var api = new ApiWrapper();
在您的viewmodel中:

self.ajaxParams.subscribe(function (params) {
    self.waiting(true);
    api.getArticles(params).done(function (data) {
        self.articles(data.items);
    }).fail(function (err) {
        // show error
    }).always(function () {
        self.waiting(false);
    });
});

您确定
response.success
true
?另外,我认为
initialLoadArticles
应该在您的视图模型中。是的,我还注意到,如果我将
vm.waiting(false)
放在
api.ajax.get
之外,它会起作用。@Vitaliy看到更新的答案。您确定
response.success
true
?另外,我认为
initialLoadArticles
应该在您的视图模型中。是的,我还注意到,如果我将
vm.waiting(false)
放在
api.ajax.get
之外,它会起作用。@vitali我会看到更新的答案。