AJAX学习笔记
AJAX简介
AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法,是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
XHR 创建对象
XMLHttpRequest 是 AJAX 的基础。
XMLHttpRequest 对象:
所有现代浏览器均支持 XMLHttpRequest 对象(IE5 和 IE6 使用 ActiveXObject)。
XMLHttpRequest 用于在后台与服务器交换数据。
创建 XMLHttpRequest 对象的语法:
var xhr = new XMLHttpRequest();
老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象:
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
//ActiveXObject是ie6的一个插件总称,后面的括号是选择用哪个插件
兼容性解决:
方法一:
var xhr = null;
if (window.XMLHttpRequest)//需要在前面加上window(作用是看window下有没有XHR属性),不加的话会报错
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
方法二:
try {
xhr = new XMLHttpRequest();
} catch (e) {
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
//try catch意思是尝试执行try{}有没有报错,有则执行catch{}传入错误信息参数e;
XHR 请求
如需将请求发送到服务器,我们使用 XMLHttpRequest 对象的 open()
和 send()
方法:
xhr.open("GET","test1.txt",true);
//规定请求的类型、URL 以及是否异步处理请求
xhr.send();
//将请求发送到服务器。
open(method,url,async)
参数:
- method:请求的类型(打开方式);GET 或 POST(类似于表单Form的method属性)
- url:文件在服务器上的位置(Form-action)
- async:是否异步 true(异步)或 false(同步)
异步:非阻塞模式 前面的代码不会影响后面代码的执行
同步:阻塞 前面的代码会影响后面代码的执行
send(string)
(Form-submit):
- string:仅用于 POST 请求
GET 还是 POST?
与 POST 相比,GET 更简单也更快,并且在大部分情况下都能用。
GET是读取,而POST是修改的意思;
GET通过url地址传输
POST通过浏览器内部传输
GET在url?后面传输数据
POST用send()
传输,并要设置请求头setRequestHeader()
申明发送的数据类型
用GET时,接受了后端传来的数据后会缓存到cookie里,当后端数据更新时,由于url地址没有改变,直接从cookie里读取数据,所以并不能读取到更新数据,而POST由于是用send()
作为参数传输,所以不存在缓存问题;
可以在url后加一个随机数或者时间戳解决:
xhr.open('get','2.get.php?username='+encodeURI('刘伟')+'&age=30&' + new Date().getTime(),true);
//时间戳前的&不能少
当用GET传输中文时,会发生乱码,要用encodeURI()
进行转成url编码,而POST在申明数据类型时已经自动用encodeURI()
进行转码了
然而,在以下情况中,请使用 POST 请求:
- 无法使用缓存文件(更新服务器上的文件或数据库),也因为有缓存文件,所以GET方式相对不安全
- 向服务器发送大量数据(POST 没有数据量限制)
- 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠(GET只能发送字符串类型的数据)
当使用 async=true 时,请规定在响应处于 **onreadystatechange **事件中的就绪状态时执行的函数:
xhr.onreadystatechange = function() {
if ( xhr.readyState == 4 ) {
if ( xhr.status == 200 ) {
alert( xhr.responseText );
} else {
alert('出错了,Err:' + xhr.status);
}
}
}
on readystate change : 当readyState改变的时候触发
readyState
: ajax工作状态
0(未初始化)还没有调用open()方法
1(载入)已调用send()方法,正在发送请求
2(载入完成)send()方法完成,已收到全部响应内容
3(解析)正在解析响应内容
4(完成)响应内容解析完成,可以在客户端调用了
status
: 服务器(请求资源)状态,http状态码(如404 Not Found未找到页面,200 OK请求已成功)
responseText
: ajax请求返回的内容以本文形式存放到这个属性下面,字符串类型
responseXML
:返回XML形式的内容
数据获取
用open()
打开的接口里返回的数据是一堆数据,后端可以根据需要返回一个类数组类型或者类json类型的数据,方便前端使用;
后端可以用json_encode()
方法自动根据数据转换成类数组类型或者类json类型;
数据传到前端后,前端可以用JSON方法把一个对象转成对应字符串也可以把字符串转成对应对象;
JSON(大写)是一个对象,下面有两个方法:
stringify : 可以把一个对象转成对应字符串
parse : 可以把字符串转成对应对象
var arr = [1,2,3];
var j = {left:100};
alert( JSON.stringify(arr) );
alert( JSON.stringify(j) );
var s1 = '[100,200,300]';
var a1 = JSON.parse(s1);
AJAX 跨域
跨域的问题
- 域:域名
- 跨域请求(访问):一个域名下的文件请求另外一个域名下的资源,就产生了跨域请求
- AJAX有跨域请求限制
跨域问题的解决:
- 通过flash请求资源
- 通过服务端中转代理(中转),例如通过PHP中转,因为PHP也有请求资源的方法,但不涉及跨域,所以PHP先请求到资源,再用AJAX访问PHP的资源;
- JSONP
AJAX跨域解决之JSONP:
JSONP : json padding
通过<script>
标签的src属性加载外部资源
src的作用 : 加载(包含指定的外部文件)
可以跨域包含且没有跨域问题;
被包含的资源可以是任何类型的文件(可以是txt,php等);
他只关注被包含的文件的内容是否是合法的JS;
用法:
- 在资源加载进来之前定义好一个函数,这个函数接收一个参数(数据),函数里面利用这个参数做一些事情
- 然后需要的时候通过
<script>
标签加载对应远程文件资源,当远程的文件资源被加载进来的时候,就会去执行我们前面定义好的函数,并且把数据当作这个函数的参数传入进去
<script>
function fn(data) {
alert(data);//123
}
</script>
<script src="2.txt"></script>
2.txt文件内容:(类比后端文件)
fn([1,2,3]);
等于执行了fn函数并将[1,2,3]数据当作这个函数的参数传入
这样做等于是给数据命名了,因为如果加载的资源数据没有命名,就只能加载到数据,却操作不了。
又有一个问题,现在是加载到<script src="2.txt"></script>
这里就会马上执行fn函数了,但我们需要按需加载fn函数,应该要动态添加<script src="2.txt"></script>
而不是一开始就放在HTML里;
oBtn.onclick = function() {
//当按钮点击的时候再去加载远程资源,让他执行
var oScript = document.createElement('script');
oScript.src = '2.txt';
document.body.appendChild(oScript);
}
因为后端已经写好了默认加载2.txt文件是执行fn函数的,但是当其他函数也需要2.txt的数据呢?
这是应该让后端不要写死是默认执行fn函数,而是用参数让前端决定执行什么函数;
callback作为参数传到后端;
<script>
function fn1(data) {
var oUl1 = document.getElementById('ul1');
var html = '';
for (var i=0; i<data.length; i++) {
html += '<li>'+data[i]+'</li>';
}
oUl1.innerHTML = html;
}
function fn2(data) {
var oUl2 = document.getElementById('ul2');
var html = '';
for (var i=0; i<data.length; i++) {
html += '<li>'+data[i]+'</li>';
}
oUl2.innerHTML = html;
}
</script>
oBtn1.onclick = function() {
var oScript = document.createElement('script');
oScript.src = 'getData.php?callback=fn1';
document.body.appendChild(oScript);
}
oBtn2.onclick = function() {
var oScript = document.createElement('script');
oScript.src = 'getData.php?t=str&callback=fn2';
document.body.appendChild(oScript);
}
注意:执行的函数应该要作为全局的函数;