传统网站存在的问题
- 页面加载慢
- 表单提交就 如果一项内容不合格 需要重新填写所有表单的内容
- 页面跳转 重新加载页面 造成资源浪费 增加用户等待时间
Ajax
浏览器提供的方法,可以实现页面无刷新更新数据
定义
在不刷新页面的情况下,使用异步对象ajax(XMLHttpRequest)向服务器后台发送请求报文,拿到响应的数据之后,通过DOM操作方式局部更新当前页面
Ajax的应用场景
- 页面上拉加载更多数据
- 列表数据无刷新分页
- 表单项离开焦点数据验证
- 搜索框提示文字下拉列表
Ajax 运行环境
需要在网站环境中才能生效 可以使用Node创建的服务器
Ajax使用步骤
- 创建ajax对象
var xhr = new XMLHttoRequest()
IE5 和 IE6 不支持 new XMLHttoRequest() 要使用new ActiveXObject(“Microsoft.XMLHTTP”); - 告诉ajax对象要向什么地方 以什么方式发生请求
xhr.open('get','请求地址')
- 发送请求 请求体
xhr.send()
- 获取服务器端响应到客户端的数据 ajax 发送需要时间 通过ajax底下的
onload
方法xhr.onload = function(){ //xhr.responseText 存储的地址 }
xhr.status
可以获取 http状态码
可以通过xhr.getRequestHeader('Content-Type')
获取响应头文件的类型
Ajax运行原理及实现
-
服务器大多数情况下会以JSON对象作为响应数据的格式,客户端拿到数据时会将JSON数据和HTML字符串进行品阶 并以DOM的形式响应到页面中
-
在http请求与响应的过程汇总,无论是请求参数还是响应内容,如果是对象类型,最终都会被转换为对象字符串进行传输---->{‘name’,‘ll’}
-
将json字符串转换为json对象
JSON.parse()
请求参数传递
get请求参数
xhr.open('get','https://gitbook.cn/?ref=csdn')
代码示例
<body>
<input type="text" name="uname">
<input type="text" name='upwd'>
<input type="submit" id='btn'>
<script>
//创建ajax对象
var xhr = new XMLHttpRequest();
var btn = document.querySelector('#btn');
var uname = document.querySelector('input[name=uname]');
var upwd = document.querySelector('input[name=upwd]');
btn.onclick = function(){
var unameV = uname.value;
var upwdV = upwd.value;
console.log(unameV);
xhr.open('get','http://localhost:3000/second?uname='+unameV+'&upwd='+upwdV);
xhr.send();
xhr.onload = function() {
};
}
</script>
</body>
post请求方式
必须在请求报文中明确的声明请求参数的类型
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
请求数据写在send中
xhr.send('name=zhangsan&age=20');
代码示例
<body>
<input type="text" name="uname">
<input type="text" name='upwd'>
<input type="submit" id='btn'>
<script>
//创建ajax对象
var xhr = new XMLHttpRequest();
var btn = document.querySelector('#btn');
var uname = document.querySelector('input[name=uname]');
var upwd = document.querySelector('input[name=upwd]');
btn.onclick = function(){
var unameV = uname.value;
var upwdV = upwd.value;
var paramts = 'uname='+unameV+'&upwd='+upwdV;
xhr.open('post','http://localhost:3000/post');
//设置参数格式
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.send(paramts);
xhr.onload = function() {
console.log(xhr.responseText)
};
}
</script>
</body>
请求参数格式
application/x-www-form-urlencoded
name=zhangsan&age=20&sex=男application/json
{name: ‘zhangsan’,age: 20,sex: ‘男’}
在请求头忠厚指定Content-Type属性的值是application/json
,就是在告诉服务器端当前请求的参数的格式是json
JSON.stringify
将json对象转换为json字符串 send中只能传入字符串
注意:
- get请求是不能提交json对象数据格式的,传统网站的表单提交也是不支持json对象数据格式的
- json对象就是没有方法的对象—字面量对象,构造函数就是Object
在服务器端获取传入数据 使用bodyParser
时要使用app.use(bodyParser.json());
Ajax 异步编程
事件处理函数也是回调函数的一种
Ajax异步请求
Object.assign(被覆盖对象,覆盖对象) 对象覆盖
获取服务器端的响应
Ajax状态码
xhr.readystate
//获取Ajax状态码
在创建ajax对象,配置ajax对象,发送请求,以及接受完服务器端响应数据,在这个过程中每一步都对应一个数值,这个数值就是ajax状态码
- 0:请求未初始化 还没有调用open()
- 1 请求已经建立,但是还没有发送 —没有调用send()
- 2 请求已经发送
- 3 请求正在处理中,通常响应中已经有部分数据可以使用了
- 4 响应已经完成,响应数据已经接收完了,可以获取并使用服务器的响应了
onreadystatechange 事件
当Ajax状态码发生变化时将自动触发该事件
这个事件要写在send()方法的前面
两种获取服务器端响应方式的区别
- onload事件 onreadystatechange事件
- onload不兼容ie低版本 onreadystatechange可以
- onload不需要判断ajax状态码 onreadystatechange需要
- onload被调用一次 onreadystatechange被调用多次
低版本ie浏览器的缓存问题
在请求地址不发生变化的情况下,只有第一次请求会真正发送到服务器端,后续的请求都会从浏览器的缓存中获取结果,及时服务器端的数据更新了,客户端依然拿到的是缓存中的旧数据
解决方案
在请求地址的后面加请求参数,保证每一次请求中的请求参数的值不相同
ajax错误处理
-
网络通畅,服务器端能接受到请求,服务器端返回的结果不是预期结果
xhr.status 获取http状态码 -
404找不到
-
500 服务器端错误
-
网络中断 请求无法发生
会触发xhr下面的onerror事件
xhr.onerror=function(){}
原生Ajax封装
代码
function ajax(options) {
//存储默认值
var defaults = {
type: 'get',
url: '',
data: {},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success: function(){},
error:function(){}
}
//对象覆盖 直接修改原对象
Object.assign(defaults,options);
//创建ajax对象
var xhr = new XMLHttpRequest();
var params = '';
//用户存入对象数据的话就进行遍历 并将它存为字符串
for (var key in defaults.data) {
params += key + '=' + defaults.data[key] + '&';
}
//将字符串最后的一个&去掉
params = params.slice(0, params.length - 1);
//判断用户传入的请求类型
if (defaults.type == 'get') {
//get 拼接字符串
defaults.url = defaults.url + '?' + params;
}
//在open方法中传入请求类型,和请求地址
xhr.open(defaults.type, defaults.url);
if (defaults.type == 'post') {
//get
//用户希望的向服务器端请求的参数类型
var contentType = defaults.header['Content-Type'];
//设置请求参数格式的类型
xhr.setRequestHeader('Content-Type', contentType);
// var contentType = xhr.getResponseHeader('Content-Type');
console.log(contentType)
if (contentType == 'application/json') {
console.log(contentType);
//将对象格式转为对选哪个字符串 并传递
xhr.send(JSON.stringify(defaults.data));
} else {
//发送请求
console.log(params)
xhr.send(params);
}
} else {
xhr.send();
}
xhr.onload = function () {
//获取响应头的数据
let getContentType = xhr.getResponseHeader('Content-Type');
//服务器端返回的数据
var responseText = xhr.responseText;
//判断是否包含application/json
if (getContentType.includes('application/json')) {
//从json字符串转换为json数据
responseText = JSON.parse(responseText);
console.log(responseText);
}
if (xhr.status == 200) {
//传入xhr对象是为了查看更多的信息
defaults.success(responseText, xhr);
} else {
defaults.error(responseText, xhr);
}
}
}
var testObj = {
url: 'http://localhost:3000/frist',
success: function (response) {
console.log('success');
console.log(response);
},
};
ajax(testObj);