【高级功能】使用 Ajax(续)

1. 准备向服务器发送数据

Ajax 最常见的一大用途是向服务器发送数据。最典型的情况是从 客户端发送表单数据,即用户在form元素所含的各个 input 元素里输入的值。下面代码展示了一张简单的表单:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>基本表单</title>
    <style>
        .table{display: table;}
        .row{display: table-row;}
        .cell{display: table-cell;padding: 5px;}
        .lable{text-align: right;}
    </style>
</head>
<body>
<form id="fruitform" method="post" action="http://127.0.0.1:8080/form">
    <div class="lable">
        <div class="row">
            <div class="cell lable">Apples:</div>
            <div class="cell"><input name="apples" value="5" /></div>
        </div>
        <div class="row">
            <div class="cell lable">Bananas:</div>
            <div class="cell"><input name="bananas" value="2" /></div>
        </div>
        <div class="row">
            <div class="cell lable">Cherries:</div>
            <div class="cell"><input name="cherries" value="20" /></div>
        </div>
        <div class="row">
            <div class="cell lable">Total:</div>
            <div id="results" class="cell">0 items</div>
        </div>
    </div>
    <button id="submit" type="submit">Submit Form</button>
</form>
</body>
</html>

这个例子中的表单包含三个input元素和一个提交button 。这些input元素让用户可以指定三种不同的说过各自要订购多少,button则会将表单提交给服务器。

1.1 定义服务器

显而易见,这里需要为这些示例创建处理请求的服务器。这里再一次使用Node.js,原因主要是它很简单,而且用的是Javascript。新建 fruitcalc.js脚本文件如下:

var http = require(‘http‘);
var querystring = require(‘querystring‘);

function writeResponse(res,data){
    var total = 0;
    for(fruit in data){
        total += Number(data[fruit]);
    }
    res.writeHead(200,"OK",{
        "Content-Type":"text/html",
        "Access-Control-Allow-Origin":"http://localhost:63342"
    });
    res.write(‘<html><head><title>Fruit Total</title></head><body>‘);
    res.write(‘<p>‘+total+‘ item ordered</p></body></html>‘);
    res.end();
}

http.createServer(function(req,res){
    console.log("[200] "+req.method+" to "+req.url);
    if(req.method == "OPTIONS"){
        res.writeHead(200,"OK",{
            "Access-Control-Allow-Header":"Content-Type",
            "Access-Control-Allow-Methods":"*",
            "Access-Control-Allow-Origin":"*"
        });
        res.end();
    }else if(req.url == ‘/form‘&& req.method == ‘POST‘){
        var dataObj = new Object();
        var contentType = req.headers["content-type"];
        var fullBody = ‘‘;

        if(contentType){
            if(contentType.indexOf("application/x-www-form-urlencode") > -1){
                req.on(‘data‘,function(chunk){
                    fullBody += chunk.toString();
                });
                req.on(‘end‘,function(){
                    var dBody = querystring.parse(fullBody);
                    dataObj.apples = dBody["apples"];
                    dataObj.bananas = dBody["bananas"];
                    dataObj.cherries = dBody["cherries"];
                    writeResponse(res,dataObj);
                });
            }else if(contentType.indexOf("application/json") > -1){
                req.on(‘data‘,function(chunk){
                    fullBody += chunk.toString();
                });
                req.on(‘end‘,function(){
                    dataObj = JSON.parse(fullBody);
                    writeResponse(res,dataObj);
                });
            }
        }
    }
}).listen(8080);

脚本中高亮部分:writeResponse函数。这个函数会在提取请求的表单值之后调用,它负责生产对浏览器的响应。当前,这个函数会创建简单的HTML文档,效果如下:

这个响应很简单,实现效果是让服务器计算出了用户通过form中各个input元素所订购的水果总数。服务器得端脚本的其余部分负责解码客户端用Ajax发送的各种可能数据格式。

1.2 理解问题所在

上面的图片清楚的描述了想要用Ajax解决的问题。

当提交表单后,浏览器会在新的页面显示结果。这意味着两点:

* 用户必须等待服务器处理数据并生成响应;

* 所有文档上下文信息都丢失了,因为结果是作为新文档进行显示的。

这就是应用Ajax的理想情形了。可以异步生成请求,这样用户就能在表单被处理时继续与文档进行交互。

2. 发送表单

向服务器发送数据的最基本方式是自己收集并格式化它。下面代码展示了添加到前面的HTML文档 example.html 的一段脚本。用的就是这种方式:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>手动收集和发送数据</title>
    <style>
        .table{display: table;}
        .row{display: table-row;}
        .cell{display: table-cell;padding: 5px;}
        .lable{text-align: right;}
    </style>
</head>
<body>
<form id="fruitform" method="post" action="http://127.0.0.1:8080/form">
    <div class="lable">
        <div class="row">
            <div class="cell lable">Apples:</div>
            <div class="cell"><input name="apples" value="5" /></div>
        </div>
        <div class="row">
            <div class="cell lable">Bananas:</div>
            <div class="cell"><input name="bananas" value="2" /></div>
        </div>
        <div class="row">
            <div class="cell lable">Cherries:</div>
            <div class="cell"><input name="cherries" value="20" /></div>
        </div>
        <div class="row">
            <div class="cell lable">Total:</div>
            <div id="results" class="cell">0 items</div>
        </div>
    </div>
    <button id="submit" type="submit">Submit Form</button>
</form>
<script>
    document.getElementById("submit").onclick = handleButtonPress;

    var httpRequest;
    function handleButtonPress(e){
        //对表单里的button元素而言,其默认行为是用常规的非Ajax方式提交表单。这里不想让他发生,所以调用了preventDefault方法
        e.preventDefault();
        var form = document.getElementById("fruitform");
        //收集并格式化各个input的值
        var formData ="";
        var inputElements = document.getElementsByTagName("input");
        for (var i = 0; i < inputElements.length; i++){
            formData += inputElements[i].name + "=" + inputElements[i].value +"&";
        }
        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;
        //数据必须通过POST方法发送给服务器,并读取了HTMLFormElement的action属性获得了请求需要发送的URL
        httpRequest.open("POST",form.action);
        //添加标头来告诉服务器准备接受的数据格式
        httpRequest.setRequestHeader(‘Content-Type‘,‘application/x-www-form-urlencoded‘);
        //把想要发送给服务器的字符串作为参数传递给send方法
        httpRequest.send(formData);
    }

    function handleResponse(){
        if(httpRequest.readyState == 4 && httpRequest.status == 200){
            document.getElementById("results").innerHTML = httpRequest.responseText;
        }
    }
</script>
</body>
</html>

效果图如下:

服务器响应表单提交后返回的HTML文档会显示在同一页,而且该请求是异步执行的。

3. 使用FormData对象发送表单数据

另一种更简洁的表单收集方式是使用一个FormData对象,它是在XMLHttpRequest的第二级规范中定义的。

3.1 创建 FormData 对象

loading... 代码问题,正在解决

4. 发送JSON数据

Ajax不止用来发送表单数据,几乎可以发送任何数据,包括JavaScript对象表示法(JavaScript Object Notation,JSON)数据,而它几乎已经成为一种流行的数据格式了。Ajax扎根于XML,但这一格式很繁琐。当运行的Web应用程序必须传输大量XML文档时,繁琐就意味着带宽和系统容量方面的实际成本。

JSON经常被称为XML的“脱脂”替代品。JSON易于阅读和编写,比XML更紧凑,而且已经获得了广泛支持。JSON发源于JavaScript,但它的发展已经超越了 JavaScript,被无数的程序包和系统理解并使用。

以下是一个简单的JavaScript对象用JSON表达的例子:

{"bananas":"2","apples":"5","cherries":"20"}

这个对象有三个属性:bananas、apples和cherries。这些属性的值分别是2、5和20。

JSON的功能不如XML丰富,但对许多应用程序来说,那些功能是用不到的。JSON简单、轻量和富有表现力。下面例子演示了发送JSON数据到服务器有多简单,修改前例的JavaScript部分如下:

<script>
    document.getElementById("submit").onclick = handleButtonPress;

    var httpRequest;
    function handleButtonPress(e){
        e.preventDefault();
        var form = document.getElementById("fruitform");

        var formData = new Object();
        var inputElements = document.getElementsByTagName("input");
        for(var i=0;i<inputElements.length;i++){
            formData[inputElements[i].name] = inputElements[i].value;
        }

        httpRequest = new XMLHttpRequest();
        httpRequest.onreadystatechange = handleResponse;
        httpRequest.open("POST",form.action);
        httpRequest.setRequestHeader("Content-Type","application/json");
        httpRequest.send(JSON.stringify(formData));
    }

    function handleResponse(){
        if(httpRequest.readyState == 4 && httpRequest.status == 200){
            document.getElementById("results").innerHTML = httpRequest.responseText;
        }
    }
</script>

这段脚本,创建了一个新的Object,并定义了一些属性来对应表单内各个input元素的name属性值。可以使用任何数据,但 input元素很方便,而且能和之前的例子保持一致。

为了告诉服务器正在发送JSON数据,把请求的Content-Type标头设为 application/json,就像这样:

httpRequest.setRequestHeader("Content-Type","application/json");

用JSON对象和JSON格式进行相互的转换。(大多数浏览器能直接支持这个对象,但也可以用下面的网址里的脚本来给旧版的浏览器添加同样的功能:https://github.com/douglascrockford/JSON-js/blob/master/json2.js )JSON对象提供了两个方法:

在上面的例子中,使用了stringify方法,然后把结果传递给XMLHttpRequest 对象的send方法。此例中只有数据的编码方式发生了变化。提交表单的效果还是一样。

5. 发送文件

可以使用FormData 对象和type 属性为 file 的input 元素向服务器发送文件。当表单提交时,FormData对象会自动确保用户选择的文件内容与其他的表单值一同上传。下面的例子展示了如何以这种方式使用FormData对象。

(待续。。。)

时间: 2024-12-23 12:36:57

【高级功能】使用 Ajax(续)的相关文章

阿里云移动端播放器高级功能---视频下载

基本介绍优酷.爱奇艺.腾讯等主流的视频类App都有视频离线下载的功能,主要目的是在wifi下将视频离线在本地,然后在无网或者4G的情况下去观看离线视频.那么阿里云播放器也提供了视频下载的功能.这个功能主要针对的是点播视频,也就是vid播放的视频的下载. 主要问题m3u8如何下载?我们知道m3u8是一个索引文件,真正的视频文件是各个ts的分片,那么如何下载成一个完成的视频呢?如何对视频下载进行多线程控制?在一些app中,多个视频同时下载被认为是高级VIP才有的功能.如何实现断点续传?当在下载过程中

PHP命名空间规则解析及高级功能

日前发布的PHP 5.3中,最重要的一个新特性就是命名空间的加入.本文介绍了PHP命名空间的一些术语,其解析规则,以及一些高级功能的应用,希望能够帮助读者在项目中真正使用命名空间. 在这里中我们介绍了PHP命名空间的用途和namespace关键字,在这篇文章中我们将介绍一下use命令的使用以及PHP如何解析命名空间的名字的. 为了便于对比,我定义了两个几乎一样的代码块,只有命名空间的名字不同. < ?php // application library 1 namespace App\Lib1;

block高级功能

/* -*- c++ -*- */ /* * Copyright 2004,2007,2009,2010,2013 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License a

MVC5+EF6--12 Entity Framework高级功能

近期学习MVC5+EF6,找到了Microsoft的原文,一个非常棒的系列,Getting Started with Entity Framework 6 Code First using MVC 5,网址:http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-appli

iOS开发——UI篇Swift篇&amp;玩转UItableView(二)高级功能

UItableView高级功能 1 class UITableViewControllerAF: UIViewController, UITableViewDataSource, UITableViewDelegate { 2 3 var titleString:String! 4 5 @IBOutlet var titleLabel:UILabel! 6 @IBOutlet var listTableView : UITableView! 7 @IBOutlet var editDoneBut

[渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序使用高级功能

这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第十二篇:为ASP.NET MVC应用程序使用高级功能 原文:Advanced Entity Framework 6 Scenarios for an MVC 5 Web Application 译文版权所有,谢绝全文转载--但您可以在您的网站上添加到该教程的链接. 在之前的教程中,您已经实现了继承.本教程引入了当你在使用实体框架Code

打开phpmyadmin显示高级功能尚未完全设置部分功能未激活

问题:老师,打开phpmyadmin显示高级功能尚未完全设置部分功能未激活,应该如何解决? 这是前一阵子学生问过我的一个问题,今天我就在博客里解答你的疑问吧. 总共三步可以搞定 1.导入相关文件到数据库 2.更改配置文件config.inc.php 3.给于root用户相关权限 详细过程如下: 先找到 phpMyAdmin所在目录,在 phpMyAdmin 目录下有个examples文件夹,该文件夹里面有个 create_tables.sql 数据库文件.(如果你的 phpMyAdmin 是老版

项目开发--&gt;高级功能汇总

祭奠曾经逝去的青春…… 1.高级功能汇总-->Memcached之ASP.NET实现

为SSD编程(4)——高级功能和内部并行

原文 http://codecapsule.com/2014/02/12/coding-for-ssds-part-4-advanced-functionalities-and-internal-parallelism/ 在这个部分,我将简要的介绍一些SSD的主要功能,如TRIM和预留空间.我同样会介绍SSD中不同等级的内部并行. 5. 高级功能 5.1 TRIM 让我们假设一个程序向SSD所有的逻辑块地址都写入文件,这个SSD当然会被装满.然后删除这些文件.文件系统会报告所有的地方都是空的,尽

十二、Python高级功能之Mysql数据库模块

Python高级功能之Mysql数据库模块 安装python mysql组件 # yum -y install MySQL-python.x86_64 以下根据实例来说明: >>> import MySQLdb >>> conn = MySQLdb.connect(user='root',passwd='2wdc%RDX',host='localhost')  #连接数据库(到服务器的连接) >>> cur = conn.cursor()  # 创建游