我在用户多次单击按钮时遇到一些问题,而我想在第一个Ajax请求执行其操作时抑制/忽略点击。例如,如果用户想要将商品添加到他们的购物车,他们会点击添加按钮。如果他们多次单击“添加”按钮,则会因为尝试将重复项插入购物车而抛出PK违规。
所以这里提到了一些可能的解决方案:Prevent a double click on a button with knockout.js 在这里:How to prevent a double-click using jQuery?
但是,我想知道下面的方法是否是另一种可能的解决方案。目前我使用透明" Saving"覆盖整个屏幕的div试图阻止点击,但仍有一些人设法双击。我假设因为他们可以点击比div可以渲染更快。为了解决这个问题,我试图使用全局变量锁定Ajax调用。
按钮
<a href="#" class="disabled btn btn-default" data-bind="click: $root.AddItemToCart, visible: InCart() == false"><span style="SomeStyles">Add</span></a>
Knockout按下按钮
执行此脚本 vmProductsIndex.AddItemToCart = function (item) {
if (!app.ajaxService.inCriticalSection()) {
app.ajaxService.criticalSection(true);
app.ajaxService.ajaxPostJson("@Url.Action("AddItemToCart", "Products")",
ko.mapping.toJSON(item),
function (result) {
ko.mapping.fromJS(result, vmProductsIndex.CartSummary);
item.InCart(true);
item.QuantityOriginal(item.Quantity());
},
function (result) {
$("#error-modal").modal();
},
vmProductsIndex.ModalErrors);
app.ajaxService.criticalSection(false);
}
}
调用此脚本
(function (app) {
"use strict";
var criticalSectionInd = false;
app.ajaxService = (function () {
var ajaxPostJson = function (method, jsonIn, callback, errorCallback, errorArray) {
//Add the item to the cart
}
};
var inCriticalSection = function () {
if (criticalSectionInd)
return true;
else
return false;
};
var criticalSection = function (flag) {
criticalSectionInd = flag;
};
// returns the app.ajaxService object with these functions defined
return {
ajaxPostJson: ajaxPostJson,
ajaxGetJson: ajaxGetJson,
setAntiForgeryTokenData: setAntiForgeryTokenData,
inCriticalSection: inCriticalSection,
criticalSection: criticalSection
};
})();
}(app));
问题仍然是我可以垃圾邮件点击按钮并获得主键违规。我不知道这种方法是否有缺陷,Knockout在第一次Ajax调用完成之前还没有足够快速更新按钮的可见绑定,或者每次他们点击按钮时都是新的实例criticalSectionInd已创建,而不是真正充当全局变量。
如果我错了,我将使用其他帖子中提到的方法,只是这种方法似乎更容易实现,而无需重构我的所有按钮来使用jQuery One()特征
答案 0 :(得分:1)
您应该在回调方法中设置app.ajaxService.criticalSection(false);
。
现在你在if子句的末尾执行这行代码,而不是在成功或错误回调中执行,所以它在你的ajax调用完成之前执行。
vmProductsIndex.AddItemToCart = function (item) {
if (!app.ajaxService.inCriticalSection()) {
app.ajaxService.criticalSection(true);
app.ajaxService.ajaxPostJson("@Url.Action("AddItemToCart", "Products")",
ko.mapping.toJSON(item),
function (result) {
ko.mapping.fromJS(result, vmProductsIndex.CartSummary);
item.InCart(true);
item.QuantityOriginal(item.Quantity());
app.ajaxService.criticalSection(false);
},
function (result) {
$("#error-modal").modal();
app.ajaxService.criticalSection(false);
},
vmProductsIndex.ModalErrors);
}
}
你可以使用&#34;禁用&#34;从knockout绑定以防止要触发锚标记的click绑定。
这是一个小片段。只需在操作开始时将标志设置为true,并在执行完成后再将其设置为false。与此同时,禁用绑定会阻止用户执行点击功能。
function viewModel(){
var self = this;
self.disableAnchor = ko.observable(false);
self.randomList = ko.observableArray();
self.loading = ko.observable(false);
self.doWork = function(){
if(self.loading()) return;
self.loading(true);
setTimeout(function(){
self.randomList.push("Item " + (self.randomList().length + 1));
self.loading(false);
}, 1000);
}
}
ko.applyBindings(new viewModel());
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<a href="#" data-bind="disable: disableAnchor, click: doWork">Click me</a>
<br />
<div data-bind="visible: loading">...Loading...</div>
<br />
<div data-bind="foreach: randomList">
<div data-bind="text: $data"></div>
</div>
&#13;