utton
方法:加上屬性disabled=“disabled” 或者 disabled=“true”
<button id="btn" disabled="disabled">確定</button> 2>Javascript里 <script> $("#btn").attr("disabled","true"); $("#btn").attr("disabled","disabled"); $("#btn").attr("disabled","false"); $("#btn").removeAttr("disabled","disabled"); </script>
a標簽
方法:在點擊一次后,解除綁定。
<a id="mybtn">button</a> <script> $("a").click(function(){ alert("1"); $(this).css("color","#CCC"); $(this).unbind("click"); }) </script>
或者:
常開發中經常會用到表單提交,如果表單沒有做防重復提交,可能會引起系統業務邏輯異常,導致系統數據錯亂
下面我給出一套常用的解決方案,前端用javascript鎖防止重復點擊,后端驗證session里面的token值防止重復提交
一、引起表單重復提交有以下幾種常見場景
二、前端
session中設置一個token
String token=UUID.randomUUID().toString();
session.setAttribute("formToken", token);
表單html
<html>
<head>
<title>員工信息</title>
</head>
<body>
<form method="post" action="/postForm">
姓名:<input type="text" name="userName">
年齡:<input type="text" name="age">
性別:<input type="text" name="sex">
<input type="hidden" name="formToken" value="${formToken}">
<input type="button" value="保存" onclick="infoSave()">
</form>
</body>
</html>
js防止重復點擊
<script>
var isSaving=false;
function infoSave() {
if(isSaving) {
return false;
}
isSaving=true;
Ajax.post('https://xxx.xxx.xxx/infoSave',params).then(function(res){
isSaving=false;
if(res.code==200){
alert("修改成功");
}else{
alert(res.message);
}
window.location.reload();
});
}
</script>
三、服務端
String Token1=request.getParameter("formToken");
String Token2=(String) session.getAttribute("formToken");
if (Token1 !=null && Token1.equals(Token2)) {
// 處理表單提交 ...
// 刪除標識符
session.removeAttribute("formToken");
}else{
// 重復提交,給出錯誤提示
}
四、總結
一般情況下采用JS腳本方式和服務端方式兩種結合已可防止表單重復提交,針對特殊業務要求的可采用數據庫唯一性約束限制等方式來強制保證業務邏輯上的數據唯一要求。
所周知,函數節流(throttle)是 JS 中一個非常常見的優化手段,可以有效的避免函數過于頻繁的執行。
舉個例子:一個保存按鈕,為了避免重復提交或者服務器考慮,往往需要對點擊行為做一定的限制,比如只允許每300ms提交一次,這時候我想大部分同學都會到網上直接拷貝一段throttle函數,或者直接引用lodash工具庫
btn.addEventListener('click', _.throttle(save, 300))
其實除了 JS 方式, CSS 也可以非常輕易的實現這樣一個功能,無需任何框架庫,一起看看吧
CSS 實現和 JS 的思維不同,需要從另一個角度去看待這個問題。
比如這里的需要對點擊事件進行限制,也就是禁用點擊事件,想想有什么方式可以禁用事件,沒錯,就是pointer-events;
然后是時間的限制,每次點擊后需要自動禁用300ms,時間過后重新恢復,那么,有什么特性和時間以及狀態恢復有關呢?沒錯,就是animation;
除此之外,還需要有觸發時機,這里是點擊行為,所以必然和偽類:active有關聯。
因此,綜合分析,實現這樣一個功能需要用到pointer-events、animation以及:active,那么如何將這些思路串聯起來呢?
思考3秒...
你想到了嗎?
其實這種場景可以理解成是對 CSS 動畫的控制,比如有一個動畫控制按鈕從禁用->可點擊的變化,每次點擊時讓這個動畫重新執行一遍,在執行的過程中,一直處于禁用狀態,是不是就達到了“節流”的效果了?
接下來看看具體實現
假設有一個按鈕,綁定了一個點擊事件
<button onclick="console.log('保存')">保存</button>
這時的按鈕連續點擊就會不斷地觸發,效果如下
下面定義一個關于pointer-events的動畫,就叫做 throttle 吧
@keyframes throttle {
from {
pointer-events: none;
}
to {
pointer-events: all;
}
}
很簡單吧,就是從禁用到可點擊的變化。
接下來,將這個動畫綁定在按鈕上,這里為了方便測試,將動畫設置成了2s
button{
animation: throttle 2s step-end forwards;
}
注意,這里動畫的緩動函數設置成了階梯曲線,step-end,它可以很方便的控制pointer-events的變化時間點。
如下示意,pointer-events在0~2秒內的值都是none,一旦到達2秒,就立刻變成了all,由于是forwards,會一直保持all的狀態
最后,在點擊時重新執行一遍動畫,只需要在按下時設置動畫為none就行了
這個技巧之前在這篇文章中有更詳細的介紹: CSS 實現按鈕點擊動效的套路
實現如下
button:active{
animation: none;
}
為了演示方便,我們暫時把顏色變化也加在動畫里
@keyframes throttle {
from {
color: red;
pointer-events: none;
}
to {
color: green;
pointer-events: all;
}
}
現在如果文字是red,表示是禁用態,只有是green,才表示可以被點擊,非常清晰明了,如下
下面是最終點擊對比效果,很好地限制了點擊頻率
完整代碼如下,就這么幾行,如果需要改限制時間,直接改動畫時間就行了
button{
animation: throttle 2s step-end forwards;
}
button:active{
animation: none;
}
@keyframes throttle {
from {
pointer-events: none;
}
to {
pointer-events: all;
}
}
借用這種思路,也可以很輕松的實現節流的效果。而且為了更好的體驗,可以用上真正的按鈕禁用
btn.disabled=true
具體思路是這樣的,通過:active去觸發transition變化,然后通過監聽transition回調去動態設置按鈕的禁用狀態,實現如下
定義一個無關緊要的過渡屬性,比如opacity
button{
opacity: .99;
transition: opacity 2s;
}
button:not(:disabled):active{
opacity: 1;
transition: 0s;
}
然后監聽transition的起始回調
// 過渡開始
document.addEventListener('transitionstart', function(ev){
ev.target.disabled=true
})
// 過渡結束
document.addEventListener('transitionend', function(ev){
ev.target.disabled=false
})
這樣做的最大好處是,這部分禁用的邏輯是完全和業務邏輯是解耦的,可以在任意時候,任意場合下無縫接入,也不受框架和環境影響,效果如下
以上通過 CSS 的思路實現了類似“節流”的功能,相比 JS 實現而言,實現更精簡、使用更簡單,沒有框架限制,下面一起總結一下實現要點:
原文鏈接:https://juejin.cn/post/7165828047520661534
*請認真填寫需求信息,我們會在24小時內與您取得聯系。