【背景描述】
最近在做一个关于赠送礼物的小页面,页面上首先会提示当前剩余可送的礼物数,然后提供了一个输入框,用户输入要赠送的礼物数量,点击提交到后台完成赠送礼物,然后回到页面刷新当前剩余可送礼物数。
页面如下:
这里涉及到几个重点:
(1)输入框的验证问题。
(2)两个ajax后台交互操作,一个是获取剩余可送礼物数,一个是赠送礼物的时候去后台更新数据。
(3)点击确定按钮之后,上述两块的顺序执行问题。
【问题描述】
整个页面的流程是这样的:
(1)页面初始化加载[剩余可送礼物数],ajax后台交互取数据。
(2)必须等待[剩余可送礼物数]加载完成以后,用户输入[赠送份数]。
(3)点击[确认提交],首先验证输入是否合法,然后还要再刷新一遍剩余可送礼物数,也就是这里必须还要进行一次ajax后台交互取数据的操作。重新刷新一遍的意义在于,防止用户在页面停留过久没有刷新导致页面显示的数据跟后台数据不一致,或者是有多个用户共享这一个[剩余可送礼物数],要保证可赠送总数的递减保持一致。
(4)比较[赠送份数]是否超过[剩余可送礼物数],这一步必须在[剩余可送礼物数]加载完成之后执行。
(5)输入验证通过以后,执行赠送礼物的ajax操作,完成以后刷新[剩余可送礼物数]。
小结:ajax获取[剩余可送礼物数] -> 用户提交[赠送份数] -> 输入验证开始 -> 再刷新ajax获取[剩余可送礼物数] -> 比较[赠送份数]和[剩余可送礼物数] ->验证通过,赠送礼物ajax -> ajax刷新[剩余可送礼物数]
遇到的问题:
1. ajax获取[剩余可送礼物数]封装在一个function里 getGiftsNum(),在确认提交的function中,直接调用了getGiftsNum(),但是程序并没有按照我们希望的顺序去执行,因为这里的ajax默认是异步执行的,受后台操作的复杂程度以及前台网络通讯等等原因造成数据返回不及时,也就是用户提交以后还没有得到最新的[剩余可送礼物数]就直接进行后面的判断了,导致出错。
2. 尝试过将ajax获取[剩余可送礼物数]的过程改成同步执行,取数据的顺序正常了,但是没法控制用户多次点击按钮,造成ajax多次重复提交。
3. 要防止用户在数据还没有加载完全的时候,疯狂点击按钮造成的ajax多次提交的问题。
【解决方案】
#1#-> 为防止用户多次点击按钮造成ajax多次提交,可以在ajax的beforeSend()和success()函数中添加按钮关闭和按钮打开控制,一旦开始执行ajax后台交互,就锁住按钮,直至结束返回数据再打开按钮,保证ajax在点击按钮之后只执行一次。
<button type="button" class="weui-btn" id="btn_submit" onclick="Submit()">确认赠送</button>
请注意 $("#btn_submit").attr("disabled", "disabled"); 这种方式只对button有效,对<a>标签无效。
//打开按钮
function openSubmit() {
// $("#btn_submit").attr("disabled", false);
$("#btn_submit").text("确认提交");
$("#btn_submit").removeAttr('disabled');
$("#btn_submit").css("background-color", "#EBA656");
}
//关闭按钮
function disableSubmit(value) {
// $("#btn_submit").attr("disabled", true);
$("#btn_submit").attr("disabled", "disabled");
$("#btn_submit").text(value);
$("#btn_submit").css("background-color", "grey");
}
在ajax中打开按钮和关闭按钮的操作
function getGiftsNum() {
$.ajax({
data: {
//请求参数
data: request_data
},
// async: false, //改成同步
type: "post",
url: "getGiftsNumServlet",
dataType: "json",
beforeSend: function () {
disableSubmit("正在加载...");
},
success: function (dataArray) {
// console.log(dataArray.count); //获取后台传递过来的json串
limitNum = dataArray.count;
console.log("---getPrezentsNum----limitNum: " + limitNum);
$("#limitNum").text(limitNum); //数据填充到页面上
openSubmit(); //打开按钮
},
error: function (e) {
alert("ajax发生错误!" + e.status);
openSubmit();
},
complete: function () {
openSubmit();
}
});
}
#2#-> 解决因为ajax异步执行导致的无法顺序执行的问题,不要直接调用函数,重写ajax取[剩余可赠送礼物数]的过程,在complete()函数里去执行后面的判断操作,避免数据还没有取到就执行后续判断流程了。
【完整代码】
<body></body> 样式用的是微信官方的WeiUI
<body>
<div class="weui-form-preview">
<div class="weui-form-preview__hd">
<div class="weui-form-preview__item">
<label class="weui-form-preview__label mytitle2">剩余的礼物数量</label>
<em class="weui-form-preview__value" style="font-weight: bold;color: blue;" id="limitNum"></em>
</div>
</div>
</div>
<div>
<div class="weui-cells__title mytitle">确认赠送份数</div>
<div class="weui-cells">
<div class="weui-cell">
<div class="weui-cell__bd">
<input class="weui-input" type="number" pattern="/(^[1-9]\d*$)/" placeholder="请输入赠送份数" id="shareNum">
</div>
</div>
</div>
</div>
<div class='demos-content-padded'>
<button type="button" class="weui-btn weui-btn_primary mybutton" id="btn_submit" onclick="Submit()">确认赠送</button>
</div>
</body>
<script><script>
<script type="text/javascript">
//打开按钮
function openSubmit() {
// $("#btn_submit").attr("disabled", false);
$("#btn_submit").text("确认提交");
$("#btn_submit").removeAttr('disabled');
$("#btn_submit").css("background-color", "#EBA656");
}
//关闭按钮
function disableSubmit(value) {
// $("#btn_submit").attr("disabled", true);
$("#btn_submit").attr("disabled", "disabled");
$("#btn_submit").text(value);
$("#btn_submit").css("background-color", "grey");
}
var limitNum = -1; //最大可赠送礼物数
//页面初始化的时候,获取最大可赠送礼物数
function getGiftsNum() {
$.ajax({
data: {
data: request_data //请求参数
},
// async: false, //改成同步
type: "post",
url: "getGiftsNumServlet",
dataType: "json",
beforeSend: function () {
disableSubmit("正在加载..."); //关闭按钮
},
success: function (dataArray) {
// console.log(dataArray.count); //获取后台传递过来的json串
limitNum = dataArray.count;
console.log("---getGiftsNum----limitNum: " + limitNum);
$("#limitNum").text(limitNum); //数据填充到页面上
openSubmit(); //打开按钮
},
error: function (e) {
alert("ajax发生错误!" + e.status);
openSubmit(); //打开按钮
},
complete: function () {
openSubmit(); //打开按钮
}
});
}
//----按钮提交----
function Submit() {
console.log("------点击了一次按钮!--------");
//----取输入框的值进行判断-----
var shareNum = document.getElementById("shareNum").value;
// --1.输入框为空的情况--
if (shareNum === "") {
alert("请输入正确的赠送礼物份数!");
}
// --2.输入框为非正整数的情况--
else if (!(/(^[1-9]\d*$)/.test(shareNum))) {
alert("份数应为正整数!");
$("#shareNum").val(""); //清空输入框
}
else {
limitNum = -1;
// limitNum = document.getElementById("limitNum").innerText;
console.log("-------设置limitNum为初始值 -1 ---------");
//重复去后台取数据的过程-----getGiftsNum()------
console.log("---我在submit里面--去后台获取数据------");
$.ajax({
data: {
data: request_data //请求参数
},
// async: false, //改成同步
type: "post",
url: "getGiftsNumServlet",
dataType: "json",
beforeSend: function () {
disableSubmit("正在提交中..."); //关闭按钮
},
success: function (dataArray) {
// console.log(dataArray.count); //获取后台传递过来的json串
limitNum = dataArray.count;
console.log("---getGiftsNum----limitNum: " + limitNum);
$("#limitNum").text(limitNum); //数据填充到页面上
openSubmit(); //打开按钮
},
error: function (e) {
alert("ajax发生错误!" + e.status);
openSubmit(); //打开按钮
},
complete: function () {
// openSubmit();
console.log("limitNum已经取数完毕!");
console.log("shareNum: " + shareNum);
console.log("limitNum: " + limitNum);
// --3.赠送份数 > 可赠送总份数的情况--
if (parseInt(shareNum) > parseInt(limitNum)) {
alert("赠送份数不能超过当前可赠送礼物总份数!");
$("#shareNum").val(""); //清空输入框
openSubmit(); //打开按钮
}
// --4.输入正常的情况,进行下一步 赠送礼物ajax--
else{
$.ajax({
data: {
shareNum: shareNum, //赠送份数
data: request_data2 //请求参数
},
type: "post",
url: "submitFPServlet",
dataType: "json",
beforeSend: function () {
disableSubmit("正在送礼物中..."); //关闭按钮
},
success: function (dataArray) {
console.log(dataArray.result); //获取后台传递过来的json串
console.log("正在赠送礼物中....");
openSubmit(); //打开按钮
},
error: function (e) {
alert("ajax发生错误!" + e.status);
openSubmit(); //打开按钮
},
complete: function () {
$("#shareNum").val("");
showSubmit(); //打开按钮
console.log("赠送完成");
getGiftsNum(); //刷新当前剩余的可赠送礼物数
}
});
}
}
});
}
}
//------页面初始化加载--------
$(document).ready(function () {
getGiftsNum(); //获取可赠送的最大礼物数
});
</script>
关于输入框验证,主要分了以下4种情况
1. 输入为空值
2. 输入为负数或者0,验证必须输入正整数
3. 输入值超过可赠送的最大礼物数
4. 输入正常,进入下一步赠送礼物操作。