PHP+AJAX
1. 什么是 AJAX
AJAX = Asynchronous JavaScript And XML
(异步JavaScript
及XML
)AJAX
是Asynchronous JavaScript And XML
的首字母缩写。AJAX 使用 JavaScript 在 web 浏览器与 web 服务器之间来发送和接收数据。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
1.1 同步和异步
- 同步: 前端发请求, 必须等到后端响应完成,才允许发送另一个请求
- 异步: 前端发请求后不等待后端响应结果继续执行,后端响应完成通过事件方式告知前端处理信息
异步最常用的处理形式就是回调函数
1.2 优点是什么
- 传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
- 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
2. AJAX 请求流程
2.1 创建 XMLHttpRequest 对象
- 所有现代浏览器均支持
XMLHttpRequest
对象(IE5 和 IE6 使用 ActiveXObject)
。 XMLHttpRequests
用于在后台与服务器交换数据。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。- 创建 XMLHttpRequest 对象的语法:
xhr=new XMLHttpRequest();
- 为了应对所有的现代浏览器,包括
IE5
和IE6
,可以检查浏览器是否支持XMLHttpRequest
对象。如果支持,则创建XMLHttpRequest
对象。如果不支持,则创建ActiveXObject
:
var xhr;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xhr = new XMLHttpRequest();
} else {
// code for IE6, IE5
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
2.2 监听请求
- 当使用
async=true
时,请规定在响应处于 onreadystatechange 事件中的就绪状态时执行的函数: - 当请求被发送到服务器时,我们需要执行一些基于响应的任务。每当 readyState 改变时,就会触发 onreadystatechange 事件。readyState 属性存有 XMLHttpRequest 的状态信息。
属性 | 状态 |
---|---|
onreadystatechange | 每当 readyState 属性改变时,就会调用该函数。 |
readyState | - 存有 XMLHttpRequest 的状态。从 0 到 4 发生变化。0: 请求未初始化,1: 服务器连接已建立,2: 请求已接收,3: 请求处理中,4: 请求已完成,且响应已就绪 |
status | 200: “OK”,404: 未找到页面 |
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
document.getElementById("myDiv").innerHTML = xhr.responseText;
}
};
2.3 初始化请求参数
- 如需将请求发送到服务器,我们使用
XMLHttpRequest
对象的open()
方法: open(method,url,async)
method:请求的类型;GET 或 POST
url:文件在服务器上的位置
async:true(异步)或 false(同步)
2.4 发送请求
- 我们使用
XMLHttpRequest
对象的send()
send(string)
,将请求发送到服务器。string:仅用于 POST 请求
3. Ajax-GET 请求
GET
简单也快,并且在大部分情况下都能用。- 然而,在以下情况中,需要使用 POST 请求:
无法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST
比GET
更稳定也更可靠
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
//1.创建xhr对象
var xhr = new XMLHttpRequest();
//2.监听请求
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
//3.初始化请求参数
xhr.open("GET", "get.php", "true");
//4.发送请求
xhr.send(null);
</script>
</body>
</html>
- get.php 里面的内容
<?php
$user['name'] = 'Nicola';
$user['email'] = 'admin@aoebbs.cn';
//将数组转为json字符串必须用echo不能用return
echo json_encode($user);
4. Ajax-POST 请求
4.1 方式一,模拟表单类型
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
//1.创建xhr对象
var xhr = new XMLHttpRequest();
//2.监听请求
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
//3.初始化请求参数
xhr.open("POST", "post.php", "true");
//4.设置请求头
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//准备请求参数
var use = {
email: "admin@nicola.com",
password: "123456",
};
//把js对象转为json字符串
var data = JSON.stringify(use);
//5.发送请求
xhr.send(data);
</script>
</body>
</html>
- post.php 内容
<?php
// print_r($_POST);
$data = key($_POST);
// echo $data;
//$data转为可以处理的数据
$user = json_decode($data);
print_r($user);
$user = json_decode($data, true);
print_r($user);
4.2 方式二 直接用 json
- 设置请求头,这里变更为 json,请求格式是 utf-8
xhr.setRequestHeader("Content-type", "application/json;charset=utf-8");
- 用原始文件流的方式来接收
php://input
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
//1.创建xhr对象
var xhr = new XMLHttpRequest();
//2.监听请求
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
//3.初始化请求参数
xhr.open("POST", "post2.php", "true");
//4.设置请求头,这里变更为json,请求格式是utf-8
xhr.setRequestHeader("Content-type", "application/json;charset=utf-8");
//准备请求参数
var use = {
email: "admin@nicola.com",
password: "123456",
};
//把js对象转为json字符串
var data = JSON.stringify(use);
//5.发送请求
xhr.send(data);
</script>
</body>
</html>
- post2.php 内容
<?php
// print_r($_POST);
$data = file_get_contents('php://input');
// 用原始文件流的方式来接受
// $data = key($_POST);
// // echo $data;
// //$data转为可以处理的数据
$user = json_decode($data);
print_r($user);
$user = json_decode($data, true);
print_r($user);
4. Ajax-FormData 请求
- 可直接序列化表单数据
- 可直接被 Ajax 识别,所以可以不设置请求头
- 除了表单数据外,也可用于普通数据
FormData
的方式向服务器发送表单数据,服务器端会自动识别FormData
对象,可以不用设置请求头,通过JSON.parse()
;把服务器返回的 JSON 转为 JS 对象。判断用户输入的信息和服务器端的信息是否匹配。如果不匹配则向网页中输出相应的提示信息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
// - 可直接序列化表单数据
// - 可直接被 Ajax 识别,所以可以不设置请求头
// - 除了表单数据外,也可用于普通数据
//1.创建xhr对象
var xhr = new XMLHttpRequest();
//2.监听请求
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
//3.初始化请求参数
xhr.open("POST", "formdata.php", "true");
//formdata
var data = new FormData();
data.append("username", "admin");
data.append("password", "admin8888");
//5.发送请求
xhr.send(data);
</script>
</body>
</html>
- formdata.php 内容
<?php
print_r($_POST);
5. 用 FormData 完成一个用户登录与验证的小案例
5.1 前端界面设计
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>用户登录表单验证</title>
</head>
<body>
<p>用户登录表单验证</p>
<!-- onsubmit="return false": 禁用表单的默认提交,改为自定义的Ajax提交 -->
<form
action=""
method="POST"
style="display: grid; gap: 15px;"
onsubmit="return false"
>
<input
type="email"
name="email"
placeholder="请输入你的邮箱"
required
autofocus
/>
<input
type="password"
name="password"
placeholder="请输入你的密码"
required
/>
<button>提交</button>
</form>
<script>
// 1. 获取表单和按钮
var form = document.querySelector("form");
var btn = document.querySelector("form button");
// 2. 给按钮绑定点击事件,进行Ajax请求
btn.onclick = function () {
// 1. 创建Ajax对象
var xhr = new XMLHttpRequest();
// 2. 监听请求
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
// 将jsonl转js对象
var res = JSON.parse(xhr.responseText);
console.log(res);
switch (res.status) {
case 0:
case 1:
error = res.message;
break;
default:
error = "非法操作,请联系管理员";
}
// 将提示显示到表单中
var span = document.createElement("span");
span.innerHTML = error;
span.style.color = "red";
form.appendChild(span);
}
};
// 3. 初始化请求参数
xhr.open("POST", "formdata.php", true);
// FormData
var data = new FormData(form);
data.append("login_time", new Date().getTime());
// 5. 发送请求
xhr.send(data);
};
// 清除提示信息
var inputs = document.querySelectorAll("input");
for (var i = 0; i < inputs.length; i++) {
inputs[i].oninput = function () {
if (btn.nextElementSibling !== null)
form.removeChild(btn.nextElementSibling);
};
}
</script>
</body>
</html>
5.2 数据表
- 密码都是123456
5.3 ajax 验证用户登录
FormData
的方式向服务器发送表单数据,服务器端会自动识别FormData
对象// FormData
var data = new FormData(form);
data.append("login_time", new Date().getTime());
// 5. 发送请求
xhr.send(data);
- pod方式连接数据库
- sql语句从数据库查询已有的用户数据
php $sql = 'SELECT COUNT(`id`) FROM `user` WHERE `email`=? AND `password`=? LIMIT 1';
- 预处理sql语句,防止sql注入
- 传入参数,通过post方式获取用户提交的表单信息,核对邮箱和加密后的密文是否和数据库中储存的信息一致
<?php
// print_r($_POST);
//pod方式连接数据库
$pdo = new PDO('mysql:host=localhost;dbname=php', 'root', 'root123456');
//sql语句从数据库查询已有的用户数据
$sql = 'SELECT COUNT(`id`) FROM `user` WHERE `email`=? AND `password`=? LIMIT 1';
// 预处理sql语句,防止sql注入
$stmt = $pdo->prepare($sql);
//传入参数,通过post方式获取用户提交的表单信息,核对邮箱和加密后的密文是否和数据库中储存的信息一致
$stmt->execute([$_POST['email'], md5($_POST['password'])]);
// 获取用户的信息
$user = $stmt->fetch(PDO::FETCH_NUM);
// 判断是否验证成功
if ($user[0] == 1) echo json_encode(['status' => 1, 'message' => '验证通过']);
else echo json_encode(['status' => 0, 'message' => '邮箱或密码错误']);
6. 总结
ajax不是新的编程语言,而是一种使用现有标准的新方法。在不重新加载整个页面的情况下,ajax是与服务器交换数据并更新部分网页的艺术。但是通过做一个登录验证的小案例,我也发现了ajax的一些缺点,比如,ajax
不支持浏览器back按钮,AJAX暴露了与服务器交互的细节,涉及到了安全的问题,不容易调试等等。但是他的优点还是非常突出的,所以就看程序员怎么去使用了。