目录
任务3:通过 Ajax 请求发表评论
在与服务器的交互过程中,经常会使用表单收集用户输入的信息。而在使用
Ajax 技术发送表单数据时,将众多表单元素的数据构造成符合规范的请求字符串
却是一件繁琐的事情。接下来就以发表评论功能为例,介绍表单数据处理中的常
用方法。了解 Ajax 技术实现评论功能的优势请扫描二维码。
提供新闻阅读及评论功能的 /newspages/news_read.jsp 运行效果如图7.1所示。
图 7.1 新闻阅读及评论页面
使用 Ajax 技术实现发表评论功能的要求如下。
(1)单击 "发表" 按钮,将评论相关的数据以 Ajax 方式发送到服务器处理。
(2)因使用 Ajax 技术,服务器保存评论数据后,仅需反馈执行结果,无需
跳转至新闻查询和展示功能页面。
(3)客户端收到服务器反馈后,如果评论发表成功,操作页面 DOM 元素,将
评论数据添加到评论列表顶端;若发表失败,则显示相应提示信息。
7.3.1 jQuery 解析表单数据的方法
因为要使用 Ajax 技术改造评论功能,首先修改表单,不再通过传统提交方式发送
数据,如示例 8 所示。
示例 8
<ul class = "classlist">
<form action = ""method = "post">
<input type = "hidden" id = "nid" name = "nid" value = "${news.nid}"/>
<table widht = "80%" align = "center">
……//省略部分表单元素
<tr><td>
<input id = "commentSubmit" name="submit" value = "发表" type = "button"/>
<tr><td>
</table>
</form>
</ul>
编写 JavaScript 脚本,使用 jQuery 提取表单数据并发送 Ajax 请求,如示例 9 所示。
示例 9
$(document).ready(function(){
var $formArea = $("ul.classlist").eq(2); //定位表单所在区域
var $commentInputs = $formArea.find(":input"); //获取所有表单元素
var $commentArea = $formArea.prev("ul").children(); //获取评论展示区域
$("#commentSubmit").click(function()){//"发表" 按钮的单击事件
var parmsArray = $commnetInputs.serializeArry(); //将表单编码成数组格式
var queryString = $.param(paramsArray); //将数据序列化成请求字符串
$.post("util/news?opr = addComment",queryString,afterComment,"JSON");
function afterComment(data){
}
});
});
jQuery de .serializeArray() 方法会从一组表单元素中检测有效控件,将其序列化成
由 name 和 value 两个属性构成的 JSON 对象的数组。其中有效控件的规则包括。
- 元素不能被禁用。
- 元素必须有 name 属性。
- 选中的 checkbox 才是有效的。
- 选中的 radio 才是有效的。
- 只有触发提交时间的 submid 按钮才是有效的。
- file 元素不会被序列化。
以发表评论的表单为例, .serializeArray() 方法对其有效控件进行序列化额结果如下
所示。
[
{
name :"nid",
value :"隐藏域 nid 的 value"
},
{
name:" :cauthor",
value:"文本框cauthor 的value"
},
{ name:"cip",
value:"文本框 cip 的 value"
},
{
name:"ccontent",
value:"文本框 ccontent 的 value"
}
}
在此结果基础上可以进行表单验证等工作。
如果要发送数据到服务器,还需进一步将数据序列化成请求字符串的形式,可以通
过 $.param() 方法实现。序列化的结果如下所示。
nid = 元素的值 &cauthor = 元素的值 &cip = 元素的值 &ccontent = 元素的值
以上结果就可以随 Ajax 请求发送到服务器了。
知识扩展
jQuery 还提供了一种简便的方式来实现将表单序列化成请求字符串的功能,
即对表单元素调用 .serialize() 方法。
$commentInputs.serialize();
实际上,.serialize() 方法内部就是使用 $.param() 方法对 .serializeArray()方
法做了一个简单包装,对于不需要中间环节的情景,可以更方便地完成表单数据
的序列化。
7.3.2 服务器端的处理和响应
评论数据随 Ajax 请求发送到服务器后,服务器端相关功能的实现相应的调整如下。
示例 10
reponse.setContentType("text/html;charset=UTF-8");
printWriter out = response.getWriter();
……//省略部分代码
try{
if(opr.equals("addComment")){//添加评论
String cauthor = request.getParameter("cauthor");
……//省略部分从请求中取值的代码
Comment comment = new Comment();
……//省略封装 comment 对象的代码
String result = "",//存储执行结果,需要发送回客户端
try {
commentsService.addCommnet(comment);
result = "sucess"; //"sucess"表示执行成功
}catch (Exception e){
result = "评论添加失败!请联系管理员查找原因"; //失败则记录错误提示
}
DataFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
out.print([{\"result\":\""+result+"\",\"cdate\":\""
+df.format(comment.getCdate())+"\"}]);
}……省略其他功能实现
}catch(Exception e){
e.printStackTrace();
}
out.flush();
out.close();
服务器端处理后不再进行跳转,直接将结果及评论发表日期以 JSON 格式返回客户端。
响应数据格式如下。
[{"result":"执行结果","cdate","评论发表时间"}]
客户端接收到响应结果后进行判断,如果执行成功,则将新评论添加到评论列表开头,
否则提示错误信息。
示例11
function afterComment(data){
if(data[0].result == "success"){ //发表成功,将评论添加到评论列表开头
//使用模板构建一条新评论
var $newComment = $("<tr><td>留言人:</td><td>cauthor</td>"
+"<td>IP: </td><td>cip</td>"
+"<td>留言时间:</td><td>cip</td>"
+"<tr><td colspan= \"6\">ccontent</td></tr>"
+"<tr><td colspan=\"6\"><hr/></td></tr>");
//将模板中的关键字替换为具体数据,部分数据来自序列化表单得到的 paramsArray
$(paramsArray).each(function()){
//根据变量名查找关键字并替换为相应的值
$newComment.find("td:contains('"+this.name+"')")
.text(this.value);
});
$newComment.find("td:contains('cdate')").text(data[0].cdate);
$commentArea.prepend($newComment); //将评论添加到列表开头
}else{ //发表失败则提示错误信息
alert(data[0].result);
}
}
技能训练
上机练习5——使用 Ajax 实现无刷新的新闻评论功能
需求说明
(1)参考示例 8 ~示例 11,使用 Ajax 技术实现无刷新的新闻评论功能。
(2)使用 jQuery 提供的方法序列化表单数据。