1.具体需求


 点击发送验证码 , 提示验证码发送成功.且发送验证码按钮不可点击.按钮文本呈现为60秒倒计时.

2.可能出现的问题

 当用户发送了一个验证码成功后,页面按钮呈现不可点击状态, 且用户必须等待60秒后才可点击.如果用户刷新页面呢 ?

你的一段禁用按钮的javaScript就显的没有什么约束力了.这时候页面重新加载了,发送验证码按钮依然呈现为可点击状态.

3.最小成本的改造

 那么如何以最小的代价来避免这个问题的发生嘞  ? 我首先想到的就是使用浏览器缓存,或者Cookie.解决这个重点在于,你如何捕获用户刷新了页面 , 如果我可能知道用户刷新了页面.那么我就可以在他离开页面之前设置一个标记.表明他并未在页面上等待足够的60秒.这时候如果他继续回到发送验证码这个页面.我就可以对他加以控制.

4.要准备的库

 Jquery.cookie.min.js

 当然如果你没有这个js库或者下载不到这个库,你可以引用我下面代码中的cdn加速地址.百度的,速度还可以.

 再或者你可以使用别的cookie插件.亦或是使用Local Storage

5.代码示例

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="http://dn-jsdelivr.qbox.me/jquery/2.1.1/jquery.js" type="text/javascript"></script>
    <script src="http://dn-jsdelivr.qbox.me/jquery.cookie/1.4.1/jquery.cookie.min.js" type="text/javascript"></script>

    <script type="text/javascript">

        var countdown = 60;
        var sending = false;

        $(function () {

            countdown = $.cookie('validateCodeCountdown');

            if (countdown>0) {
                sending = true;
                var obj = $("#btn");
                obj.attr("disabled", true);
                obj.val("重新发送(" + countdown + ")");
                settime(obj);
            }

            $(window).on('beforeunload unload', function () {
                if (sending) {
                    console.log(countdown);
                    $.cookie('validateCodeCountdown', countdown);
                }
                if (!sending) {
                    console.log(countdown);
                    $.cookie('validateCodeCountdown', 0);
                }
            });
        });


        function send() {
            sending = true;
            var obj = $("#btn");
            settime(obj);
        }

        function settime(obj) { //发送验证码倒计时
            if (countdown == 0) {
                obj.attr('disabled', false);
                obj.val("发送验证码");
                countdown = 60;
                sending = false;
                return;
            } else {
                obj.attr('disabled', true);
                obj.val("重新发送(" + countdown + ")");
                countdown--;
            }
            setTimeout(function () {
                settime(obj);
            }, 1000)
        }

    </script>
</head>
<body>

<input type="text" style="float: left"/><input type="button" value="发送验证码" style="float: left" id="btn"
                                               οnclick="send()">

</body>
</html>



6.这样做还有哪些问题

 这样做当然有问题, 如果你稍加思索,你会发现用户必须回到页面上等待足够的60秒才能够继续发送下一个验证码.如果用户退出了界面去做了其他的事情,此时时间已经过去了超过60秒,回到页面上,依然无法发送下一个验证码.

7.花更为廉价的成本继续改造

 之前的代码中你会发现.我存进Cookie的值是一个需要继续用户等待的,以秒为单位的数字.我们绝对性的忽略了用户退出页面短时间内不在回来的情况 . 以此我必须有一个时间区间.当用户发送出一个验证码时,下一个可发验证码的时间区间在哪个范围内? 不可发的时间区间在哪个范围内 . 显然 : 可发送的时间区间 : 发送时的时间+60秒后的时间 ---->未来任何时候  .不可发送的时间区间  发送时的时间----->60秒后的时间之前

 有了两个时间区间 , 我是否可以这样做 : 当用户发送验证码时 , 记录点击发送时的时间戳 (在内存里?).当我检测到用户刷新或者即将离开页面时 : 保存用户发出验证码的时间,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,


8.更为严谨的方案

 如果你的代码碰到了一个具有非常敏锐直觉的用户.他可能会注意到 你在他的浏览器上面存储了一些内容.他也许知道如何删除这段内容, 或者最基本的清除浏览器缓存.那你之前的方案就变得不可用了 . 因此我们迫切需要一种更为严谨和安全的方案限制用户的这种行为.比如 : 使用服务器来记录用户的发送行为 . 似乎我们仅仅是把之前记录cookie的那段内容搬运到了服务器也就万事大吉.还有好多想写的.