Javascript 当可观察对象发生变化时,敲除绑定不会更新
我有一个下拉按钮,它应该在ajax请求完成后可用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
<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我会看到更新的答案。