向服务器发送客户端数据有两种方式:
- 查询字符串:如果是使用查询字符串,就发起了一个GET 请求(例如访问某一个页面)
- 请求正文:如果是使用请求正文,就发起了一个POST 请求(例如发送一段表单信息)
<form action="/process" method="POST">
<input type="hidden" name="hush" val="hidden, but not secret!">
<div>
<label for="fieldColor">Your favorite color: </label>
<input type="text" id="fieldColor" name="color">
</div>
<div>
<button type="submit">Submit</button>
</div>
</form>
action ==> 表单提交地址,如果你忽略这个值,表单会提交到它被加载进来时的同一URL
method ==> 表单提交方式 get/post
name ==> 用于服务器识别字段
表单默认编码为 application/x-wwwform-urlencoded
上传文件用 multipart/form-data
主要也就是两个方式,ajax和浏览器表单提交。
浏览器表单提交有两件事需要考虑:
处理表单是哪个路径(action):也就是如何配置服务端接受表单数据的路由
浏览器发出怎样的响应。
如果表单用POST提交那么action和页面路径保持一致。因为一般页面路径是通过get发送过来的。 get 和 post路由是需要分开写的。
或者分开写:
例如 :
/contact 打开表单页面
/process-contact 用于处理表单数据
- 直接响应HTML
处理表单之后,可以直接向浏览器返回HTML(例如,一个视图)。如果用户尝试重新加载页面,这种方法就会产生警告,并且会影响书签和后退按钮。基于这些原因,我们不推荐这种方法。- 302重定向
虽然这是一种常见的方法,但这是对响应代码302(已找到)本义的滥用。HTTP1.1增加了响应代码303(请参阅其他),一种更合适的代码。除非你有理由让浏览器回到1996 年,否则你应该改用303。- 303重定向
HTTP 1.1 添加了响应代码303(请参阅其他)用来解决302 重定向的滥用。HTTP 规范明确地表明浏览器303重定向后,无论之前是什么方法,都应该使用GET 请求。这是用于响应表单提交请求的推荐方法。
通俗的说:
直接响应HTML,就是在处理表单路由里直接返回一个页面。但是有一个问题。这个路由是用来接收表单数据的,如果浏览器直接访问就会出现错误。
303重定向就是不直接返回一个页面,而是让浏览器去打开另外一个页面。
重定向指向哪里?
- 重定向到专用的成功/失败页面
这种方法需要为适当的成功或失败消息提供URL。例如,如果一个用户通过促销邮件注册,但是有一个数据库错误,你可能希望重定向/error/database。如果用户的电子邮件地址是无效的,可以重定向到/error/invalid-email。如果一切顺利,可以重定向到/promo-email/thank-you。这种方法的一个优点是便于分析:访问/promo-email/thank-you页面的人数应该和登录促销邮件的人数大致相关。而且这种方法也很容易实现。然而它还有一些缺点。这意味着你必须针对每一种可能性来分配URL,这也意味着页面设计、编写复制和维护。另一个缺点是用户体验欠佳:用户喜欢被感谢,但是他们不得不导航到之前的页面或接下来要去的页面。这是现在我们要使用的方法。在第9章将使用flash消息(不要和Adobe Flash 混淆)。- 运用flash消息重定向到原位置
由于有许多小表单分散在整个站点中(例如,电子邮件登录),最好的用户体验是不干扰用户的导航流。也就是说,需要一个不用离开当前页面就能提交表单的方法。当然,要做到这一点,可以用AJAX,但是如果你不想用AJAX(或者你希望备用机制能够提供一个好的用户体验),可以重定向回用户之前浏览的页面。最简单的方法是在表单中使用一个隐藏域来存放当前URL。因为你想有一种反馈,表明用户的提交信息已收到,所以你可以使用flash消息。- 运用flash消息重定向到新位置
大型表单通常都会有自己的页面,一旦提交就没有必要停留在这个页面上了。在这种情况下,你就要考虑一下用户接下来想去哪儿,并相应地进行重定向。例如,如果你构建一个管理界面,有一个表单用来创建旅行计划,大概能够很合理地预期用户希望在提交表单后跳转到管理页,并且列出所有的旅行计划清单。不管怎样,你应该仍旧采用flash消息为用户提供提交结果的反馈。
通俗的说:
重定向到专用的成功/失败页面:
分别定义几种提交后的可能性的页面,
提交错误去哪,提交成功去哪,数据出错去哪。
运用flash消息重定向到原位置:
可以根据表单隐藏的数据确定表单的来源,然后提交结束后直接返回到原始页面。 其实这种情况用ajax最好。
运用flash消息重定向到新位置
这种方法可说是前两者的结合,可以根据表单的隐藏数据再去确定重定向到那个位置。可以这样的项目也就比较复杂了。
get
可以直接用req.query。query保存了所有get过来的数据。
例如,如果有一个名称属性为email 的HTML 输入字段,它的值会以req.query.email 的形式传递到处理程序。
post
express不能直接处理post数据,需要引入中间件来处理。
npm install --save body-parser
然后引入:
app.use(require('body-parser')());
创建一个表单模板
/views/newsletter.handlebars
<h2>Sign up for our newsletter to receive news and specials!</h2>
<form class="form-horizontal" role="form"
action="/process?form=newsletter" method="POST">
<input type="hidden" name="_csrf" value="{{csrf}}">
<div class="form-group">
<label for="fieldName" class="col-sm-2 control-label">Name</label>
<div class="col-sm-4">
<input type="text" class="form-control"
id="fieldName" name="name">
</div>
</div>
<div class="form-group">
<label for="fieldEmail" class="col-sm-2 control-label">Email</label>
<div class="col-sm-4">
<input type="email" class="form-control" required
id="fieldName" name="email">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-4">
<button type="submit" class="btn btn-default">Register</button>
</div>
</div>
</form>
路由与中间件配置
app.use(require('body-parser')());
app.get('/newsletter', function(req, res){
// 我们会在后面学到CSRF……目前,只提供一个虚拟值
res.render('newsletter', { csrf: 'CSRF token goes here' });
});
app.post('/process', function(req, res){
// 这里通过 req.query 和 req.body出来表单数据
console.log('Form (from querystring): ' + req.query.form);
console.log('CSRF token (from hidden form field): ' + req.body._csrf);
console.log('Name (from visible form field): ' + req.body.name);
console.log('Email (from visible form field): ' + req.body.email);
// 这里303重定向到/thank-you 页面
res.redirect(303, '/thank-you');
});
8.6 处理AJAX表单
可以直接在之前的/views/newsletter.handlebars添加一个ajax代码段落
{{#section 'jquery'}}
$(document).ready(function(){
$('.newsletterForm').on('submit', function(evt){
evt.preventDefault();
var action = $(this).attr('action');
var $container = $(this).closest('.formContainer');
$.ajax({
url: action,
type: 'POST',
success: function(data){
if(data.success){
$container.html('<h2>Thank you!</h2>');
} else {
$container.html('There was a problem.');
}
},
error: function(){
$container.html('There was a problem.');
}
});
});
});
{{/section}}
配置路由:
app.post('/process', function(req, res){
// 这里用于判断如果是一个ajax请求着去处理,否则重定向到/thank-you
if(req.xhr || req.accepts('json,html')==='json'){
// 如果发生错误,应该发送 { error: 'error description' }
res.send({ success: true });
} else {
// 如果发生错误,应该重定向到错误页面
res.redirect(303, '/thank-you');
}
});
req.xhr 用于判断这个请求是否是一个ajax请求
req.accepts 试图确
定返回的最合适的响应类型。在此例中,req.accepts('json,html') 询问最佳返回格式是JSON 还是HTML:这可以根据Accepts HTTP 头信息推断出来,它是浏览器提供的可读的、有序的响应类型列表。如果是一个AJAX 请求,或者User-Agent 明确要求JSON 优先于HTML,那么就会返回合适的JSON 数据;
在此例中,我们假设所有AJAX 请求的是JSON 数据,但是并没有要求AJAX 通信必须使用JSON(事实上,“X”在AJAX中代表XML)。这个方法是jQuery 友好的,因为通常jQuery 假定所有数据都是JSON 格式的。如果想让AJAX处理程序通用,或者知道AJAX 请求使用JSON 之外的东西,你应该根据Accepts 头信息(可以根据req.accepts辅助方法轻松访问)返回一个适当的响应。如果响应完全基于Accepts头信息,你或许想看看c,这是一个可以根据客户端预期轻松做出适当响应的简便方法。如果这样做,必须保证用jQuery 发起AJAX请求时设置dataType 和accepts 属性。
共同学习,写下你的评论
评论加载中...
作者其他优质文章