在ajax(2)中,我们讲解了一些基本常见的表单请求,接下来我们在延伸一下ajax的其他知识点吧
AJAX&表单序列化提交
好比注册界面,那么多的组件,那么多的数据,我们不可能一个个去getElementById吧,还要组织数据且将数据拼成$连接的string,太麻烦 太费事,所以我们需要用该方法,大大的简化了ajax请求的操作。先上代码
//样式部分
<form action="" id="biaodan">
<p>
<label>请输入姓名
<input type="text" name="userName"/>
</label>
</p>
<p>
<label>请输入密码
<input type="password" name="psw"/>
</label>
</p>
<p>
请选择性别
<input type="radio" name="gender" value="男"/>男
<input type="radio" name="gender" value="女"/>女
</p>
<p>
请选择你的爱好
<input type="checkbox" name="hobby" value="足球"/>足球
<input type="checkbox" name="hobby" value="篮球"/>篮球
<input type="checkbox" name="hobby" value="打豆豆"/>打豆豆
<input type="checkbox" name="hobby" value="编程"/>编程
</p>
<p>
请选择你所在省份
<select name="prov" id="prov">
<option value="江苏">江苏</option>
<option value="广东">广东</option>
<option value="湖南">湖南</option>
</select>
</p>
<p>
请谈谈你的建议
<textarea name="message" id="" cols="30" rows="10"></textarea>
</p>
<p>
<input type="button" value="点击提交" id="btn"/>
</p>
</form>
<script>//js部分
// 找到相关元素
var biaodan = document.getElementById("biaodan");
var btn = document.getElementById("btn");
// 注册事件
btn.onclick = function() {
// 获取所有表单控件
var eles = biaodan.elements;
var res = []; // k=v&k=v&k=v
// 循环遍历所有的表单控件
for(var i=0; i<eles.length; i++) {
var ele = eles[i];
switch(ele.type) {
case "button":
case "submit":
case "reset":
break;
case "text":
case "password":
case "textarea":
res.push(ele.name+"="+ele.value);
break;
case "radio":
case "checkbox":
ele.checked&&res.push(ele.name+"="+ele.value);
break;
case "select-one":
var options = ele.getElementsByTagName("option");
for(var j=0; j<options.length; j++) {
options[j].selected&&res.push(ele.name+"="+options[j].value);
}
}
}
console.log(res.join("&"));
}
</script>
咱们来看看一些关键代码
biaodan.elements
就是获取form表单下,所有的表单元素子空间。
ele.type
为了去判断表单元素的类型,因为想按钮这种是没有提交的数据的,需要进行过滤
select-one
select-one对应的是select,比较特殊,不想其他的类型同type一样。
我们再结合switch,在筛选的同时,将数据进行拼接
string转json
因为接口返回的数据是string类型,绝大部分我们需要将string转成json,便于开发和解析,下面我们来讲讲几种string转json对象的方式
方法1:eval方法
var json = eval( "("+data+")");
上面的data就是一个string字符串
方法2:new Function()
//使用1
var fn = new Function("for(var i=1; i<=100; i++) {console.log(i);}");
fn();
//使用2
var data = new Function("return"+data)();
console.log(typeof data);
我们先来分析一下使用1,
在Function里面,我们可以放置一段js代码的字符串,那么那段js代码的字符串,将会被执行,我们可以看到会有100个log日志
使用2,
这里的data是一个字符串,将其return,则返回的是一个json对象
方法3:Json的方法
JSON.parse("string") 字符串--->json
JSON.stringify(json对象) json--->字符串
jquery
jquery&ajax方法
get请求
$.get("1.json",{"id":4,"name":"李伟"},function(data) {
console.log(typeof data);
});
$.get("1.json?id=4&name=阿伟",function(data) {
console.log(data);
});
我们看到两种请求地址,一种是带数据,一种是不带数据。若是带数据的,则第二个参数是一个借口调用的回调消息;若不带数据,则第二个参数是请求时的数据,第三个参数是回调消息。这里的数据已经是json对象了,我们无需再转换。
post请求
$.post("1.json",{"id":5,"name":"lucy"},function(data) {
console.log(data);
});
其实和get请求没什么区别,只不过是post方法罢了。
通用请求
$.ajax("b.json",{
// 请求类型
"type":"get",
// 传到服务器上的数据
"data": {
"name":"xiaohong",
"age":22
},
// 成功要做的事
"success":function(data) {
console.log(data);
},
"error":function(XMLHttpRequest,textStatus,errorThrown) {
console.log(errorThrown);
}
});
$.ajax是一个通用的方法,其实一共就只有两个参数,一个是请求地址,一个是对象,里面包含了请求的数据、方式、回调结果。
我们来分析一个第二个参数
type表示请求方式:get/post
data表示请求的数据,是一个json对象
success表示请求成功的回调
error表示请求失败的回调
jquery#表单序列表
如果我们用jquery去处理表单序列化,那么会比js原始方法分别很多很多,几行代码搞定
$("#btn").click(function() {
// 对form标签调用serialize()方法
var str = $("#biaodan").serialize();
console.log(str);
$.get("check.php?"+str,function(data) {})
});
从代码中一目了然,一个id是biaodan的表单,通过jquery去获取该对象,并且调用serialize()方法,那个str就是一个string,并且符合请求的数据结构,以&连接。是不是快很多?
ajax的缓存问题
ajax存在着很严重的缓存问题,假如get两次请求,都是同一个url,带着同样的参数,那么即使服务器返回200,也会被当304那样缓存,有些浏览器处理,有些浏览器没有处理。
解决方案
在请求地址后面加个随机数/时间戳
$.ajax("1.json?x="+Date.parse(new Date()),{
// 请求类型
"type":"get",
// 传到服务器上的数据
"data": {
"name":"xiaohong",
"age":22
},
// 成功要做的事
"success":function(data) {
console.log(data.content[1].name);
},
"error":function(XMLHttpRequest,textStatus,errorThrown) {
console.log(errorThrown);
}
});
我们看到了请求地址的后缀吧----->x=时间戳,虽然服务器不去处理这个x参数,但是保证了每次的请求是不同了,就避免了ajax的缓存问题。
模板引擎的使用
什么模板?那个模板?其实ajax的模板就涉及到了实际开发中。试问一下,加入我们请求了一个地址返回了很多数据,我们需要将这些数据显示成一个列表,这时候我们要怎么做?就用到了模板,将一个item做成模板,然后循环的去显示数据,就变成了一个列表。可能很抽象,咱们一步一步来分析。
模板引擎实例1
我们请求接口,将返回的数据以加载到 li 里面。
$("#btn").click(function() {
$.post("1.json",{"id":5,"name":"lucy"},function(data) {
//console.log(data);
for(var i=0; i<data.content.length; i++) {
var $li = $("<li></li>");
$li.html(data.content[i].id+":"+data.content[i].name);
$("ul").append($li);
}
});
});
{
"content":[{
"id":1,
"name":"小红"
},{
"id":2,
"name":"小花"
},
{
"id":3,
"name":"小明"
}
]
}
下面就是返回的json数据,我们去循环并取出id name 去加载到 li 中,
我们去创建一个 li 对象,并添加数据,最后添加到 ul 里面。这里的 li 就是模板,我们给这个模板去加载不同的数据,最后添加到要显示的容器里。
模板引擎实例2
模板1是视图的模板,那么模板2就是数据的模板,比如说我们需要给指定的数据,指定的位置,去替代接口返回的指定的数据,要怎么做?下面我们来看看
var str = "今天是个@rizi@的日子,我的心情非常@mood@";
// 数据字典
var dictionary = {
"rizi": "伟大",
"mood":"激动"
}
function compile(templateString,dictionaryObj) {
return templateString.replace(/\@(\w+)\@/g,function(match,$1,index,string) {
return dictionary[$1];
})
}
str = compile(str,dictionary);
document.getElementsByTagName("h1")[0].innerHTML = str;
首先 str,就是要改变的数据,@rizi@ @mood@ 表示的是修改数据的模板,dictioinay就表示接口返回的数据。其实我们发现rizi mood 对应的是接口返回数据的key,所以这数据的模板不是随便命名的,接着compile方法去替换到接口返回数据里对应的值。
模板引擎实例3
如调用接口显示表格,我们结合实例1和实例2 去综合使用
<script type="text/template" id="template">
<tr>
<td>@xuehao@</td>
<td>@xingming@</td>
<td>@age@</td>
<td>@score@</td>
</tr>
</script>
<script src="js/jquery.js"></script>
<script>
// 1 模板字符串
var str = $("#template").html();
// 2 根据模板字符串生成数据绑定函数
$.get("students.json",function(data) {
for(var i=0; i<data.students.length; i++) {
var student = data.students[i];
var DOMString = compile(str,student);
// 追加到表格末尾
$("#tb").append(DOMString);
}
});
function compile(templateString,dictionaryObj) {
return templateString.replace(/\@(\w+)\@/g,function(match,$1,index,string) {
return dictionaryObj[$1];
})
}
</script>
id为template的script就是我们的模板,里面的数据用@符号包裹,对应的分别是数据的key,然后我们去替换,对应的数据,再拼接到$("#tb")的对象里面。这样就完成了模板引擎+ajax的综合使用。其实我们还可以使用underscore.js这个库,里面提供了模板引擎的方法,以便于我们快速开发。看下面的模板引擎4
模板引擎实例4
<script type="text/template" id="template">
<tr>
<td><%=xuehao%></td>
<td><%=xingming%></td>
<td><%=age%></td>
<td><%=score%></td>
</tr>
</script>
<script src="js/underscore.js"></script>
<script src="js/jquery.js"></script>
<script>
// 1 模板字符串
var str = $("#template").html();
// 2 根据模板字符串生成数据绑定函数
var compile = _.template(str);
// 拿到数据
$.get("students.json",function(data) {
_.each(data.students,function(dictionary) {
var domStr = compile(dictionary);
// 追加到表格末尾
$("#tb").append(domStr);
});
});
</script>
主要代码就这几部
var compile = _.template(str); str表示模板字符串
var domstr = compile(dictionary); dictionary表示数据
_.each(),则是underscore的一个循环遍历方法。
Jsonp
首先ajax不支持跨域,比如说我现在的服务器是php,地址比如说是192.168.9.9,那么我只能请求该地址下的请求,不能去访问www.qq.com。
$.get("http://www.baidu.com",function(data) {
alert(data);
});
则会报错,那么我们要解决的问题就是如果去跨域请求。大家js库肯定使用过,可以应用本地的js文件,也可以使用域名去下载js来使用。关键来了,为什么script标签就可以去跨域?而网络请求就不行?Jsonp的发明者发现了这一点特性,script.src支持跨域,就有了Jsonp。
Jsonp的原理
一下是我们三个案例使用的数据,括号内的表示跨域请求回来的数据
// 函数调用语句 数据作为函数的实参
fun({
"students":[{
"xuehao":100001,
"xingming":"zs",
"age":22,
"score":78
},{
"xuehao":100002,
"xingming":"wh",
"age":22,
"score":78
},{
"xuehao":100003,
"xingming":"zn",
"age":22,
"score":78
}]
});
案例1
<script>
// 定义一个函数
function fun(data) {
console.log(data);
}
</script>
<script src="http://www.gggjsonp.js"></script>
我们利用script.src的跨域特性,去发起跨域请求。
然后在jsonp.js里面去调用window的方法fun,将跨域请求回来的数据传到window中,从而去显示。这里的www.gggjsonp.js不是在同一个服务器下的,就像我们去使用不同的js库一样去下载。
案例2
function fun(data) {
console.log(data);
}
var btn = document.getElementById("btn");
btn.onclick = function() {
// <script src="jsonp.txt"><\/script>
var oScript = document.createElement("script");
document.body.appendChild(oScript);
oScript.src="http://www.gggjsonp.js";
}
我们结合了实际应用,去手动创建script,设置src发去跨域请求。
案例3
jsonp("jsonp.txt","fun",function(data) {
console.log(data);
});
// 编写一个轮子 以后进行jsonp进比较方便
function jsonp(URL,callbackname,callback) {
window[callbackname] = callback;
// 创建script元素
var oScript = document.createElement("script");
// 添加节点
document.body.appendChild(oScript);
oScript.src= URL;
// 删除
document.body.removeChild(oScript);
}
我们对jsonp的请求过程进行了封装。
案例4
$.ajax({
dataType: 'jsonp',
url: 'http://www.a.com/user?id=123',
success: function(data){
//处理data数据
}
});
因为jquery 也提供了jsonp的调用方法。