11.3.4 格式化发送给服务器的数据

使用Ajax编写JavaScript程序的大多数时候,我们都要向服务器发送信息。例如,如果想要获取一个数据库中存储的一种特定产品的信息,可以发送表示产品的一个单独的号码。当Web服务器从XHR请求获取了号码,它在数据库中查找匹配该号码的这种产品,获取产品信息,并将其发送回Web浏览器。或者,我们可能使用Ajax来提交有用信息的整个表单,作为一个在线订单或“注册邮件新闻组”的表单的一部分。

在这些情况下,我们需要以get()和post()函数所理解的某种方式来格式化所请求的数据。传递给这两个函数的第二个参数包含了想要发送给服务器的数据,我们可以把这一数据格式化成一个查询字符串或者是一个JavaScript对象直接量,如接下来的两节所述。

常见问题GET还是POST

将数据提交给Web服务器的两个方法:GET和POST,似乎有很多相同之处。那么该使用哪一个呢?

答案是,看情况而定。在某些情况下,我们无法选择。例如,假设要给服务器上已经准备好并运行的一个服务器端脚本发送信息。换句话说,服务器端编程已经完成了,并且我们只需要使用JavaScript与其通信。在这种情况下,我们使用该脚本所期待的方法。更有可能的是,程序员设置好了脚本接收GET或POST数据。因此,可以和程序员沟通或者查看脚本来确定它使用了哪个方法,然后使用相应的jQuery函数get()或post()。

如果你(或者其他程序员)还没有编写JavaScript要与之通信的服务器端脚本,那么,可以选择方法。GET方法适合不会影响到服务器上的一个数据库或文件的状态的那些请求。

换句话说,当我们想要获取信息的时候使用它,例如询问一种特定产品的价格或者获取最流行的产品的列表。POST方法用于发送那些将会改变服务器上的信息的数据,例如,删除一个文件、更新一个数据库或者向数据库插入新的信息的一个请求。

实际上,我们可以使用任何一个方法,并且程序员经常使用一个GET方法来删除数据库信息,而使用POST方法仅仅从服务器获取信息。然而,这里有必需POST方法的一种情况。如果我们向服务器提交了很多表单数据,例如,可能包含上百个单词的一个博客帖子,那么使用POST。GET方法对于可以发送的数据的量有一个内置的限制(这个限制根据浏览器的不同而有所不同,但是通常都在数百个字符左右)。大多数时候,对于不仅仅只包含几个字段的表单,Web设计者都会使用POST。

查询字符串

你可能已经在前面见过了查询字符串:它们经常出现在一个URL的末尾,跟在一个?符号的后面。例如,www.chia-vet.com/products.php?prodID=18&sessID=1234是一个查询字符串。这个查询字符串包含了两个名/值对:prodID=18和sessID=1234。这个字符串所做的事情基本上就是创建两个变量prodID和sessID,并且把两个值存储到其中。查询字符串是在一个URL中传递信息的一种常用方法。

我们也可以以这种形式使用Ajax来格式化发送给服务器的数据。例如,假设创建了一个页面允许访问者通过单击星级数来给一部电影评定星级。例如,单击5星,向服务器提交一个5星级的评定。在这个例子中,发送给服务器的数据可能类似于rating=5。假设处理这个评级的页面的名字叫做rateMovie.php,使用Ajax向服务器发送评级的代码如下所示:


$.get('rateMovie.php','rating=5');


或者,如果使用POST方法:


$.post('rateMovie.php','rating=5');


注意:jQuery的get()和post()函数并不要求我们必须定义数据或回调函数。我们只需要提供服务器端页面的URL。然而,我们也总是提供数据。例如,在代码$.get('rankMovie.php','rating=5');中,只提供了数据和URL,而没有指定回调函数。在这个例子中,访问者只是提交一个评级,并且不需要服务器反馈或回调函数做任何事情。

如果需要给服务器发送多个名/值对,可以在每一对之间插入一个&:


$.post('rateMovie.php','rating=5&user=Bob');


然而,我们需要小心地使用这种方法,因为当有些字符插入到一个查询字符串中的时候具有特殊的含义。例如,我们使用&字符给一个字符串包含其他的名/值对,=符号给一个名字赋值。例如,如下的查询字符串是无效的:


'favFood=Mac&Cheese'//incorrect


这里的&符号本意是作为“Mac&Cheese”的一部分,但是,当用作一个查询字符串的一部分的时候,&符号被解释为另一个名/值对的开始。如果想要使用特殊的符号作为一个名/值对中的名字或值的部分,我们需要转义或者对其编码,以使它们不会错误地被认为是具有特殊含义的一个字符。例如,空格字符用%20表示,&符号用%26表示,而=用%3D表示。因此,我们需要把“Mac&Cheese”的例子写作:


'favFood=Mac%20%26%20Cheese'//properly escaped


JavaScript提供了一个方法来正确地转义字符串,即encodeURIComponent()方法。我们给encodeURIComponent()方法提供一个字符串,并且它返回正确转义的一个字符串。例如:


var queryString='favFood=’+encodeURIComponent('Mac&Cheese');

$.post('foodChoice.php',queryString);


对象直接量

对于简短而简单的数据(那些不包含任何标点符号的数据),查询字符串方法工作得很好。但是,jQuery的get()和post()函数所支持的一种更为安全的方法是,使用对象直接量来存储名/值对。正如你在本书4.8.3节所了解到的,对象直接量是用来存储名/值对的一个JavaScript方法。对象直接量的基本结构如下:


{

name1:'value1’,

name2:'value2’

}


可以直接给get()和post()函数传递一个对象直接量。例如,前面给电影评星级的代码使用查询字符串方法:


$.post('rankMovie.php','rating=5');


要使用对象直接量,可以这样重新编写代码:


$.post('rankMovie.php',{rating:5});


可以把一个对象直接量直接传递给get()和post()函数,或者首先将其存储在一个变量中并将该变量传递给get()和post():


var data={rating:5};

$.post('rankMovie.php',data);


当然,可以在传递给get()和post()函数的对象中保存任意多个名/值对:


var data={

rating:5,

user:'Bob'

}

$.post('rankMovie.php',data);


或者,直接把一个对象直接量传递给.post():


var data=$.post('rankMovie.php',

{

rating:5,

user:'Bob'

}

);//end post


jQuery的serialize()函数要为整个表单的所有名/值对创建一个查询字符串或对象直接量,可能是非常繁琐的一项工作。我们必须获取每一个表单元素的名和值,然后将它们都组合到一起来创建一个长长的查询字符串或一个较大的JavaScript对象直接量。幸运的是,jQuery提供了一个函数,使得我们可以很容易地把表单信息转换为get()和post()函数可以使用的数据。

我们可以为任何表单(或者甚至只是表单字段的一个选择)应用serialize()函数,来创建一个查询字符串。要使用它,首先创建包含了表单的一个jQuery查询,然后给它添加serialize()函数。例如,假设有一个ID为login的表单。如果想要为该表单创建一个查询字符串,可以像下面这么做:


var formData=$('#login').serialize();


var formData部分只是创建了一个新的变量,$('#login')创建了包含表单的一个jQuery选择;最后,.serialize()收集了字段名和每个字段中当前的值,并创建了一个单个的查询字符串。

要将这种方法和get()或post()函数结合起来使用,只要把序列化的结果传递给函数作为URL之后的第二个参数。例如,假设想要把登录表单的内容发送给名为login.php的表单。可以这样做:


var formData=$('#login').serialize();

$.get('login.php',formData, loginResults);


这段代码使用GET方法把访问者输入到表单中的内容发送给了login.php文件。这里的get()的最后一个参数loginResults是一个回调函数,该函数接收从服务器返回的数据并且对它做一些事情。下面将学习如何创建回调函数。