问题
要做的仍旧是很简单
- 请求
- 响应
常见的请求方式有以下几种
- img标签的src
- link标签引入css
- script标签引入js
- form标签提交
上拉加载更多(以及主动刷新页面部分内容),需要客户端主动用代码从服务端请求数据,上面的方案似乎不能满足需求了.ajax技术就是为了解决这样一个问题.
解决
通过XMLHttpRequest对象,我们可以主动的从服务器获取数据以刷新部分页面
You can retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just part of a page without disrupting what the user is doing.
XMLHttpRequest对象,不仅像字面那样只能请求XML格式的数据,还可以请求其他类型的数据,比如json等;而且支持的协议也不仅仅是http,对于ftp和file协议也是支持的
Despite its name,
XMLHttpRequestcan be used to retrieve any type of data, not just XML, and it supports protocols other than HTTP (includingfileandftp).
使用XMLHttpRequest请求json数据

客户端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>学生列表</title>
</head>
<body>
<ul id="stus">
</ul>
<script type="text/javascript">
// 获取元素
var stus_tag = document.getElementById('stus');
//1.初始化XMLHttpRequest对象
var xhr = new XMLHttpRequest();
//2.调用监听方法
xhr.onload = function () {
if (this.readyState !== 4) {return;}
// console.log(this.responseText);
// 遍历数据,展示
var stus = JSON.parse(this.responseText);
for (var i = 0; i < stus.length; i++) {
// console.log(stus[i]);
// 创建li
var li_tag = document.createElement('li');
// 设置内容
li_tag.innerHTML = stus[i].name;
// 拼接
stus_tag.appendChild(li_tag);
}
}
//3.设置请求方法和请求路径
xhr.open('GET','./students.php');
//4.发送请求
xhr.send();
</script>
</body>
</html>
服务端代码
<?php
$stus = array(
array('id' => 1,'name' => '张三', 'age' => 28),
array('id' => 2,'name' => '李四', 'age' => 29),
array('id' => 3,'name' => '王五', 'age' => 30),
array('id' => 4,'name' => '赵六', 'age' => 31),
array('id' => 5,'name' => '田七', 'age' => 32)
);
header("Content-Type:Application/json");
echo json_encode($stus);
?>
客户端代码其实有一点问题,onload函数中打印readyState
xhr.onload = function () {
console.log(this.readyState);
if (this.readyState !== 4) {return;}
.....
}永远都只能打印4

只有在onreadystatechange中才可以监听到readyState的变化,修改代码如下
xhr.onreadystatechange = function () {
console.log(this.readyState);
if (this.readyState !== 4) {return};
var stus = JSON.parse(this.responseText);
for (var i = 0; i < stus.length; i++) {
// console.log(stus[i]);
// 创建li
var li_tag = document.createElement('li');
// 设置内容
li_tag.innerHTML = stus[i].name;
// 拼接
stus_tag.appendChild(li_tag);
li_tag.id = stus[i].id;
}
}打印如下

状态说明中还有0


需要在open之前调用onreadystatechange才能打印所有状态,奇怪,确实是在open之前调用的啊,猜测是不是网速原因,执行太快了
傻了傻了,初始值是0,此时readyState还没有发生化,onreadystatechange自然不会打印0


上述示例已经完成了一个基本的应用,此外就是一些方法和属性的使用.
发送一个post请求,设置请求头,设置请求参数
给li标签添加点击事件,点击弹出对应条目的年龄

li_tag.id = stus[i].id;
li_tag.onclick = function () {
//重新发起请求,获取age
var xhr2 = new XMLHttpRequest();
xhr2.onload = function () {
if (this.readyState !== 4) {return}
alert(this.responseText);
}
xhr2.open('POST','./students.php');
//设置请求头
xhr2.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
var para = "id=" + this.id;
//传递参数
xhr2.send(para);
}
服务端代码
<?php
$stus = array(
array('id' => 1,'name' => '张三', 'age' => 28),
array('id' => 2,'name' => '李四', 'age' => 29),
array('id' => 3,'name' => '王五', 'age' => 30),
array('id' => 4,'name' => '赵六', 'age' => 31),
array('id' => 5,'name' => '田七', 'age' => 32)
);
header("Content-Type:Application/json");
if ($_SERVER['REQUEST_METHOD'] === "GET") {
echo json_encode($stus);
}elseif ($_SERVER['REQUEST_METHOD'] === "POST") {
foreach ($stus as $item) {
if ($_POST['id'] == $item['id']) {
echo $item['age'];
}
}
}
?>
设置响应头
服务端设置响应头
可以看出post状态下返回的是年龄字符串,但是response中的Content-Type却是application/json,这样虽然没有不会出现错误,但是实际上却是欺骗了客户端,正确的做法是content-type和实际返回给客户端的数据类型保持一致,改成如下

客户端设置响应头
设置responseType则由ajax将服务端返回的数据处理成json,不管服务端设置
xhr.open('GET','./students.php');
xhr.responseType = 'json';
xhr.send();
服务端去掉下面的代码
// header("Content-Type:Application/json");

因为上面的示例代码中都是对responseText进行处理,可以发现,设置xhr的responseType为json的时候,压根不返回responseText,直接返回处理好的response,因而数据渲染失败.
get请求如何传参数?
If the request method isGETorHEAD, thebodyparameter is ignored and the request body is set tonull.
这是send()函数的说明,如果是get请求,会忽略send()中的参数,并设置为null.真的是这样吗?那么是否应该把参数拼接在url后面?
get请求下send中传参
xhr.send('foo=value');

发现确实不见了
服务端打印,也见不到提交的get参数
var_dump($_GET);

那么还是把参数拼接在url后面
xhr.open('GET','./students.php?foo=value');

可以打印$_GET

也可以看到上传的参数