为了账号安全,请及时绑定邮箱和手机立即绑定

《Node与Express开发》学习笔记-第八章-表单处理

标签:
Node.js
8.1 向服务器发送客户端数据

向服务器发送客户端数据有两种方式:

  • 查询字符串:如果是使用查询字符串,就发起了一个GET 请求(例如访问某一个页面)
  • 请求正文:如果是使用请求正文,就发起了一个POST 请求(例如发送一段表单信息)
8.2 HTML表单基础
<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 ==> 用于服务器识别字段

8.3 编码

表单默认编码为 application/x-wwwform-urlencoded
上传文件用 multipart/form-data

8.4 处理表单的不同方式

主要也就是两个方式,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消息重定向到新位置
这种方法可说是前两者的结合,可以根据表单的隐藏数据再去确定重定向到那个位置。可以这样的项目也就比较复杂了。

8.5 Express表单处理
处理浏览器发送过来的数据

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 属性。

点击查看更多内容
11人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
Web前端工程师
手记
粉丝
90
获赞与收藏
327

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消