【抽獎平臺開發(2)】抽獎結果的表單提交,實現Web前後端的數據交互(HTML+JS+PHP)


前期內容提要:


在實現抽獎功能的前端搭建後,這一章主要目標是將抽獎結果通過表單方式提交至後端。

在這裏插入圖片描述
基本思路:與一般接受用戶輸入內容後形成表單提交後端不同的是,這裏需要提交至後端的是用戶的抽獎結果,這個數據不是由用戶手動輸入生成的而是JS運算產生的結果。而表單提交的數據應當是<input>標籤內的value值,這就需要將抽獎結果轉化爲一個value值傳入表單中的一個<input>標籤內。

打印至控制檯
value值默認爲空
h1 標籤存儲數據並傳值
抽獎結果
傳至HTML中的一個 div 標籤裏去
在表單內創建一個 input 標籤
value被賦值
表單提交

具體而言,如上圖所示,在表單內創建一個用於接受數據的<input>標籤,value值爲空,等待傳值;將抽獎結果通過console.log打印至控制檯,然後將控制檯上的結果傳至一個<div>標籤裏去,最後將<div>標籤裏的抽獎結果傳至<input>標籤的value內,觸發提交事件後,提交表單至後端。


一、創建數據容器並存儲數據結果
1. 創建數據容器

一方面是需要創建一個接受控制檯打印結果的<div>標籤(Id=info),另一方面是表單內創建一個用於接受數據的<input>標籤(Id=results):其中<input>標籤中定義name屬性用於後端定位接受表單數據中的哪一個具體標籤;Id屬性作爲標籤的唯一標識符用於<div>標籤(Id=info)定位<input>標籤,向其value賦值。

	<div id="info" style="display:none;"></div>

<form  id='test_form' action="gift.php"  method="get">	
     <input name="results" id="results" type="hidden" value="">
</form>

在這裏插入圖片描述

2. 將控制檯信息傳輸並存儲至<div>標籤(Id=info
<script>
var infoConsole = document.getElementById('info');
        if (infoConsole) {
        if (console) {
        	var _consolee = {
        		log:console.log
        	}
        	console.log = function(attr){
        		_consolee.log(attr);
        		var str = JSON.stringify(attr, null, 4);
        		var node = document.createElement("h1");
				var textnode = document.createTextNode(str);
				node.setAttribute("type","text");
        		node.appendChild(textnode);
        		infoConsole.appendChild(node);
        	}
        }
        function show(){
        	var type = infoConsole.getAttribute("type");
        	if (type === "0") {
        		infoConsole.style.cssText  = "width:100vw;height:40vh;";
        		infoConsole.setAttribute("type","1");
        	}else{
        		infoConsole.removeAttribute('style');
        		infoConsole.setAttribute("type","0");
        	}
        }
        }
</script>

<div>標籤(Id=info)接受到控制檯打印結果後,會自動創建<h1>子標籤存儲抽獎數據。
在這裏插入圖片描述


二、向表單內<input>標籤中的value賦值

我們需要將<div>標籤(Id=info)在接受到控制檯傳輸結果後自動創建的用於存儲結果的<h1>子標籤內容傳至表單內用於接受數據的<input>標籤內的value屬性中,以作爲表單內容予以提交。

<script>

function tijiao(){
	var obox = document.getElementById("info");
	aa = obox.firstElementChild.innerHTML;
    var input = document.getElementById("results");
	input.value=aa;

	}
</script>

值得一提的是,在這裏我僅選擇了<div>標籤(Id=info)下第一個子標籤數值予以傳輸,其目的是爲了防止數據庫被惡意抽獎結果大量寫入,當然我們可以不限定在第一個子標籤內傳值,但是需要注意原生JS在獲取子標籤時空格也會被捕獲,可以嘗試使用jQuery實現需求。

在這裏插入圖片描述


三、提交表單

表單需要在抽獎結果生成後才能被提交,因此提交表單的步驟可以放至start()函數中去,具體而言通過var form的方式定位表單的Id:test_form,使用form.submit()提交表單內容:

<script>

	function start(){
		var initial=getArrayItems(ArrList,1);
		var form = document.getElementById('test_form');
		for (var i = 0; i < initial; i++) {
			setTimeout(()=>{
				$('.gift').removeClass("selected");
				gift=$('.gift:eq('+ position[(x%8)] +')');
				gift.addClass('selected');
				x++;
				if (x==initial) {setTimeout(()=>{
					if (position[(x%8)]==2) {
						randmoney();
					}else{
						alert('恭喜獲得禮物:'+gift.text());
					}
                  	setTimeout(function(){console.log(gift.text());tijiao();form.submit();},1999);
                  	x=0;
				},10)}
			},i*150);
		}
	}
</script>

可以看到,在點擊抽獎按鈕後,開始執行start()函數,產生抽獎結果後,先彈窗通知結果(alert('恭喜獲得禮物:'+gift.text())),之後將結果打印至控制檯(console.log(gift.text())),此後控制檯打印結果會傳輸至<div>標籤(Id=info)的<h1>子標籤,之後將執行tijiao()函數將<h1>子標籤存儲結果傳至表單下<input>標籤中的value屬性中去,最後執行form.submit()提交表單。

注意:值得留意的是,由於tijiao()函數只傳輸控制檯第一條打印結果至表單下的<input>標籤中去,這裏把將抽獎結果打印至控制檯系列命令封裝在了一個延遲執行語句裏,其目的在於保證當抽獎結果是隨機紅包時,控制檯第一條打印結果是隨機紅包的具體數額而非隨機金額紅包這行文字。

在這裏插入圖片描述
此外,正是由於tijiao()函數只傳輸控制檯第一條打印結果至表單下的<input>標籤中去(防止數據庫被惡意抽獎結果大量寫入)這一邏輯,因此抽獎頁面在未刷新控制檯內打印內容時,應當且只應當允許用戶執行一次抽獎命令。這就需要爲抽獎函數添加一個定時器,用於限制用戶的抽獎次數,同時限制用戶在短時間內重複惡意點擊抽獎按鈕觸發抽獎函數。

	var repeat = 2;
	function time(){  
	  	var timer = setInterval(function() {    
	    if (repeat == 2) {
			repeat--;
	      	start();

	document.getElementById('btn1').style.backgroundColor ="#787878";	
	document.getElementById('btn1').disabled=true;		
	setTimeout(function (){
    	document.getElementById('btn1').disabled=false;
	},5000);

	    }else if (repeat == 1) {
         	setTimeout("repeat--","1000");
            clearInterval(timer);
	    } else {
          	clearInterval(timer);
          	alert('已沒有剩餘抽獎機會');
	    }
	  }, 1000);
	}

我要禮物按鈕調用函數也需要從原來的start()函數變爲現在的time()函數

		<button class="start" onclick="time()">我要禮物</button>

在初始情況下,用戶點擊我要禮物按鈕,將執行定時器,定時器檢測到repeat = 2,將執行一次start()函數,此時按鈕顏色變灰(外觀上提示用戶不要再點擊),並凍結按鈕在執行抽獎函數過程中的觸發(邏輯上阻止用戶在抽獎中重複點擊按鈕造成的抽獎函數的多次觸發),同時repeat值變成1,在1秒後repeat值歸零後退出循環,當按鈕點擊事件解凍後,用戶再次點擊我要禮物按鈕,將不再執行start()函數,彈出警告已沒有剩餘抽獎機會。除非刷新頁面(刷新頁面後:控制檯內打印內容被清空,repeat值重新變爲2,符合抽獎邏輯,允許抽獎)。


這裏講講定時器設計過程中基於幾個邏輯問題產生的版本更迭:

  1. 第一次抽獎時不應彈出警告。
//第一版
	var repeat = 1;
	function time(){  
	  	var timer = setInterval(function() {    
	    if (repeat == 0) {
	      	clearInterval(timer);
          	alert('已沒有剩餘抽獎機會');
	    } else {
	      	start();
	      	repeat--;
	    }
	  }, 1000);
	}

這是設計之初 第一版本 的定時器邏輯,後經測試發現,在執行start()函數時repeat值歸零,由於計時器1秒鐘重複執行一次,因此在執行start()函數(經測試需要5秒執行完畢)的同時會再次觸發執行repeat== 0情形下的彈出警告的操作,顯然第一次抽獎過程不應當彈出警告框。故將第一次判斷和警告框判斷分離,以解決上述問題,方案如下:

//第二版
	var repeat = 2;
	function time(){  
	  	var timer = setInterval(function() {    
	    if (repeat == 0) {
	      	clearInterval(timer);
          	alert('已沒有剩餘抽獎機會');
	    }else if (repeat == 2) {
	      	start();
	      	repeat--;
	     else {
         	setTimeout("repeat--","1000");
            clearInterval(timer);
	    }
	  }, 1000);
	}
  1. 解決用戶在短時間內重複惡意點擊抽獎按鈕觸發抽獎函數後由於不可預測repeat值而導致警告框無法彈出的問題。

根據第一版本改動後的 第二版本 定時器邏輯,經測試發現的問題是,當用戶在短時間內重複惡意點擊抽獎按鈕觸發抽獎函數後會多次執行repeat--,致使repeat在自減後不一定恆爲 0,又由於只有在repeat == 0的情況下才能彈出警告框,因此當出現用戶惡意點擊情形下,警告框將無法正常彈出。基於上述問題調整了判斷邏輯,做出如下優化:

//第三版
	var repeat = 2;
	function time(){  
	  	var timer = setInterval(function() {    
	    if (repeat == 2) {
			repeat--;
	      	start();
	    }else if (repeat == 1) {
         	setTimeout("repeat--","1000");
            clearInterval(timer);
	    } else {
          	clearInterval(timer);
          	alert('已沒有剩餘抽獎機會');
	    }
	  }, 1000);
	}
  1. 很顯然,即使使用 第三版本 的定時器邏輯,也只能保證“警告框”能夠正常彈出,並不能阻止用戶在短時間內重複惡意點擊抽獎按鈕行爲,抽獎函數被重複觸發的現實也沒有真正意義上得到解決。因此在最後版的改進中,凍結了按鈕在執行抽獎函數過程中的觸發可能性,以徹底解決上述問題。
//第四版將按鍵id命名爲btn1,並新增按鈕凍結功能。
	document.getElementById('btn1').style.backgroundColor ="#787878";	
	document.getElementById('btn1').disabled=true;		
	setTimeout(function (){
    	document.getElementById('btn1').disabled=false;
	},5000);

在這裏插入圖片描述


四、後端PHP接收數據
  • 前端通過表單的形式向後端gift.php提交數據

一般情況下用 JS 或 jQuery 的 submit 方法提交 form 表單是不會被瀏覽器攔截的,但是異步的情況下用 js 提交 form 表單就會被瀏覽器攔截,因此如果給表單設置了target="_blank",由於URL新窗口並非用戶的實時點擊而是在執行start()函數提交表單後彈出,會被瀏覽器認定爲惡意彈窗而攔截,致使無法正常提交數據至後端,需要特別注意。
在這裏插入圖片描述

<form  id='test_form' action="gift.php"  method="get">	
	<input name="results" id="results" type="hidden" value="">
</form>

此外,在抽獎完成後,數據的後端提交無需回顯至用戶界面,也不應當允許頁面自動跳轉覆蓋原來的抽獎頁面。基於此,在表單HTML部分,做出如下修改:

	<form  id='test_form' action="gift.php"  method="get" target="frameName">	
      <input name="results" id="results" type="hidden" value="">
	</form>

	<iframe src="" frameborder="0" name="frameName" style="display:none;"></iframe>
  • 後端gift.php接收前端提交過來的數據

後端獲取表單中name名爲results的標籤的value值,即表單內用於接受數據的<input>標籤內的value值,即抽獎結果。

<html>
<body>
Gift lists: <?php echo $_GET["results"]. "<br>"; ?>
</body>
</html>
  • 上線測試:
    在這裏插入圖片描述
    在這裏插入圖片描述

至此,我們成功將抽獎結果通過表單的方式提交至了後端(源碼已上傳),下一章將記錄如何將抽獎結果提交的表單上傳至數據庫,完成抽獎平臺前臺的全部開發。


後期內容提要:


如果您有任何疑問或者好的建議,期待你的留言與評論!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章