【抽奖平台开发(2)】抽奖结果的表单提交,实现Web前后端的数据交互(HTML+JS+PHP)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/deng_xj/article/details/99729936

前期内容提要:


在实现抽奖功能的前端搭建后,这一章主要目标是将抽奖结果通过表单方式提交至后端。

在这里插入图片描述
基本思路:与一般接受用户输入内容后形成表单提交后端不同的是,这里需要提交至后端的是用户的抽奖结果,这个数据不是由用户手动输入生成的而是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>
  • 上线测试:
    在这里插入图片描述
    在这里插入图片描述

至此,我们成功将抽奖结果通过表单的方式提交至了后端(源码已上传),下一章将记录如何将抽奖结果提交的表单上传至数据库,完成抽奖平台前台的全部开发。


后期内容提要:


如果您有任何疑问或者好的建议,期待你的留言与评论!

猜你喜欢

转载自blog.csdn.net/deng_xj/article/details/99729936