表单提交后分页页面标签POST实现 —— 一个小小的bug引发的思考

Posted Kiwi-Yan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表单提交后分页页面标签POST实现 —— 一个小小的bug引发的思考相关的知识,希望对你有一定的参考价值。

这几天在搞一个网页页面,由于一些不可描述的原因,这部分无法完全套用现有框架,大部分代码只能用原生的php来开发。开发过程中遇到了一个比较蛋疼的问题。所幸终于解决,现在为了描述清楚,将问题简化抽象,将解决思路整理下来,让以后长点记性。

问题是这样的:

页面有一个form表单。主要用来执行一些查询功能。查询的结果是一个集合,要通过表格显示出来。当这个集合很大的时候,就要分页显示。
代码大致如下:

<form action="xxx" method="post">
    <input type="text" name="type" placeholder="请输入要查找的类型"/>
    ...
    <input type="submit" value="查找"/>
</form>
<ul>
    <li><a href="xxx?page=1">1 <a></li>
    <li><a href="xxx?page=2">2 <a></li>
    ...
</ul>
<table>
    <thead>...</thead>
    <tbody>...</tbody>
</table>

(可能有经验的同学已经发现问题了,但是作为一个没有经验的新手还是一脸懵逼的)
问题来了。表单点提交之后显示的查询结果是正确的,但是:当点了页码之后,显示出来的结果类型不正确了,和查找时输入的类型无关了。同时表单中的值也全部重置了。
这个问题怎么解决?
先规定好bug场景吧: 点击“查找”内容正确,但是点击页码3的时候,表格内容不正确了。
1. 服务端代码定位:
先打印一下服务端的获取的参数吧,结果是page=3,但是表单里的值全都不见了!这样的话就相当于服务端查询的时候,type的值为空,因为后台逻辑里面写的如果值为空的话,sql语句就不会添加这个查询条件。所以服务器返回给前端的数据就没有按type查找了。表单里的其他值也是一样的道理。
那么这样一来,服务端的代码逻辑错误就暂时排除了。那么问题在哪呢?为什么表单里的值获取不到呢?而第一次是正确的又是为什么呢?
2. 网页代码的定位
这个时候就需要思考的问题是表单中的值到底有没有被传到服务端去。因为表单里的值是post方式提交的,所以我打开了浏览器的F12工具,然后去查Network
然后问题就出现了:第一次填写了表单之后,数据被POST到服务端,这是没有问题的;而第二次点击页码的时候,方法变成了GET,从而表单中的数据就无法提交上去了。
问题找到了,就是当点击页码的时候,form表单中的数据没有被提交到服务端去,造成这样的原因是什么呢?因为所点击的页码是一个a标签,它的链接在href中,当点击这个页码的时候,客户端就会以GET的方式往服务端发送请求。
到这里问题已经基本明确了,那么怎么解决这个问题呢?
再次描述一下背景。因为表单中填写的数据比较敏感,所以必须使用POST方式完成提交。
因为自己也不是搞web开发的,因此对于此类问题,如果原因搞明,那解决方案基本靠搜索引擎了(公司的网络可以访问Google,真心不错)。在网上搜了搜,可能是自己不会搜把,大多数都是讲如何使用mysql+php完成分页的,改了改关键字,终于找到一些可以沾边的网页。仔细看了看,主要解决办法有:
1. ajax异步提交,发送POST请求
2. 表单中添加一个隐藏的页码控件,然后在a里面添加js函数来完成提交。
接下来一个一个试:
然后就遇到问题了,我并不熟悉ajax,原理也没有搞懂,试了好多下,有“成功”的,确实从服务端接收到数据了,但是覆盖在了原来的网页上面,而且数据依然有问题(可能是表单数据发送到后台的方式不正确)。
另外一个,在表单中添加隐藏的页码控件,这里贴一个链接有兴趣可以看看(http://blog.csdn.net/arzhuo/article/details/6969516),然而此时已经花了好长时间解决这个问题了,搞到这个时候其实已经很烦了,而且这个解决办法要改动的东西太多,并不是很满意。
下班!
次日早上这个问题才终于解决。
其实仔细想一下,这个问题可以这样解决(假如没有上网搜解决方案这个过程):
1. 既然点击a使用的方法是GET,而点击“查找”按钮使用的方法是POST,那么可不可以让点击a标签实际上就是提交表单的动作呢?再把a里面的href带上。
那么可以使用jQuery这样子写:

$(function()
    $("li a").click(function(event) 
        // 获取这个a标签的href中的url
        url = $(this).attr("href");
        // 取消点击事件的默认动作
        event.preventDefault();
        // 修改form中的action动作
        $("form").attr("action", url);
        // 提交表单
        $("form").submit();
    );
);

就使用这么几行代码,直接改掉a标签的默认动作,然后问题也解决了。这个解决方案其实也是受到搜索出来的结果启发得到的,但是由于问题的具体场景不同,所以解决方案的复杂度也不一样。
2. 另一种方案:从服务端着手
既然第一次提交的数据第二次就“丢失”了,那么我可以在服务端将提交的数据保存到session中,以供后续查询使用。
这个实现起来逻辑将会比较混乱,所以跳转页面这部分算是实现了,但是又带来一些额外的问题。所以没有了继续搞下去的动力。
后记:
解决这个小小的bug的过程真的是相当煎熬,明明可以解决,但有好几次就是跳过了正确的解决方案。在这个过程中暴露了一个问题:解决问题不带脑子。
因此总结一下解决问题的方法:
首先要正确定位bug,然后思考bug的原因,寻找解决方案。
首先定位bug:
1. 对于不可重现的bug,一定要在编码期间充分准备,随时用日志记录下状态。
2. 对于可重现的bug(比如这个例子),需要采取自上而下或自下而上的方法,或者“夹逼法”。从问题的一端起,逐步去验证,直到明白是从哪个地方起出了问题,或者在哪个阶段出了问题,然后再更进一步去找。
找到问题之后,就思考原因。有一点很重要,不写、不抄、不用看不懂的代码(这个和代码复用绝对不是一回事)。每一步都想清楚,哪一步与预期不一样那一步就出了问题。
寻找解决方案这个就说来就话长,可以修改代码使他与预期一致(推荐),比如这里js模拟提交的解决方案还可以后期做修补,先把这部分所带来的影响绕过去。比如这里的session这个解决方案。等等,具体情况具体对待,但是套路一定要清楚。

以上是关于表单提交后分页页面标签POST实现 —— 一个小小的bug引发的思考的主要内容,如果未能解决你的问题,请参考以下文章

如何先分页显示数据再查询后分页显示查询数据

jQuery页面替换+php代码实现搜索后分页

我找到1个 html 页面 用来查询 mdb 数据库 带分页,挺简单的,就是分页用post实现的,师兄们帮我看看怎么改?

php form表单怎么把数据提交到本页而不跳转?

关于SpringMVC的几件小事

form表单的GET和POST请求