博客列表 >JS - Ajax基础与实战

JS - Ajax基础与实战

晴天
晴天原创
2020年05月22日 17:59:30606浏览

Ajax

1.同步与异步

以前端请求,后端响应为例

  • 同步:前端请求发送,必须等到后端响应完成,才允许发送另一个请求
  • 异步:前端发请求后不等待后端响应结果继续执行,后端响应完成通过事件通知前端处理

异步最常用的处理形式就是回调函数

2. XMLHttpRequest 对象

  • XMLHttpRequest是浏览器提供的,处理异步请求的宿主对象,而非 Js 内置对象
  • 基本流程:
    • 1.创建请求对象:new XMLHttpRequest()
    • 2.监听请求回调:onreadystatechange
    • 3.初始化请求参数:open(请求类型,请求地址,是否异步)
    • 4.发送请求:send()
  1. // 1. 创建ajax对象
  2. var xhr = new XMLHttpRequest();
  3. // 2.监听请求
  4. xhr.onreadystatechange = function () {
  5. if (xhr.readyState === 4 && xhr.status === 200) {
  6. // 控制台输出返回的数据
  7. console.log(xhr.responseText); //输出 {"name":"peter","age":23}
  8. }
  9. };
  10. // 3.初始化请求参数
  11. xhr.open("GET", "test1.php?action=demo1", true);
  12. // 4.发送请求
  13. xhr.send(null);

php 部分

  1. case 'demo1':
  2. // 创建数组
  3. $user['name'] = 'peter';
  4. $user['age'] = 23;
  5. // JSON 编码返回
  6. echo json_encode($user);
  7. break;
  • 如果是 post 请求,步骤略有不同
    • 1.创建请求对象 new XMLHttpRequest()
    • 2.监听请求回调 onreadystatechange
    • 3.初始化请求参数 open(请求类型,请求地址,是否异步)
    • 4.设置请求头 setRequestHeader()
    • 5.准备请求参数(可选) var data = ...
    • 6.发送请求 send(data)
  1. // 创建对象
  2. var xhr = new XMLHttpRequest();
  3. // 监听请求
  4. xhr.onreadystatechange = function () {
  5. if (xhr.readyState === 4 && xhr.status === 200) {
  6. console.log(xhr.responseText);
  7. // 返回值 Array
  8. // (
  9. // [name] => peter
  10. // [age] => 56
  11. // )
  12. }
  13. };
  14. // 初始化请求参数
  15. xhr.open("POST", "test1.php?action=demo2", true);
  16. // 设置请求头
  17. xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
  18. // 创建对象
  19. var user = {
  20. name: "peter",
  21. age: "56",
  22. };
  23. // 转JSON
  24. var data = JSON.stringify(user);
  25. // 发送请求
  26. xhr.send(data);

php 部分

  • 方法 1
  1. case 'demo2':
  2. print_r($_POST);
  3. // 这里输出的是 Array
  4. // (
  5. // [{"name":"peter","age":"56"}] =>
  6. // )
  7. // 所以要获取一下键
  8. $data = key($_POST);
  9. $user = json_decode($data,true);
  10. print_r($user);
  11. break;
  • 方法 2
  1. case 'demo3':
  2. $data = file_get_contents('php://input');
  3. $user = json_decode($data,true);
  4. print_r($user);
  5. break;

3. GET 请求

  • 服务器:返回JSON
  • 前端: JSON.parse()解析 JSON 字符串

4. POST 请求

  • 前端:发送JSON
  • 后端:
    • JSON 数据以表单数据类型发送,可$_POST接收
    • JSON 数组就是以 JSON 发送,php://input 流文件方式接收

5. FormData

  • 可直接序列化表单数据
  • 可直接被 Ajax 识别,所以可以不设置请求头
  • 除了表单数据外,也可用于普通数据
  1. // 创建 ajax对象
  2. var xhr = new XMLHttpRequest();
  3. // 监听数据返回
  4. xhr.onreadystatechange = function () {
  5. if (xhr.readyState === 4 && xhr.status === 200) {
  6. console.log(xhr.responseText);
  7. // 返回 Array
  8. // (
  9. // [username] => admin
  10. // [password] => admin888
  11. // )
  12. }
  13. };
  14. // 初始化请求参数
  15. xhr.open("POST", "test1.php?action=demo4");
  16. // FormData 传值
  17. var data = new FormData();
  18. data.append("username", "admin");
  19. data.append("password", "admin888");
  20. // 发送请求
  21. xhr.send(data);

php 部分

  1. case 'demo4':
  2. // 可以直接获取到值
  3. print_r($_POST);
  4. break;

6. 实战

  • 实战内容 :

    • 异步请求完成点击刷新验证码
    • 异步请求完成登录并在验证通过后自动跳转到首页
  • 演示地址: http://php.rc238.cn/0522

index.php

  1. <?php
  2. session_start();
  3. //先判断有没有sesssion 没有跳去登录
  4. if (!isset($_SESSION['user'])){
  5. die("<script>location.href='login.html';</script>");
  6. }
  7. //向下执行
  8. $session = unserialize($_SESSION['user']);
  9. //直接输出数据
  10. var_dump($session);
  11. echo "<a href='handle.php?action=logout'>点这里退出登录</a>";

login.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <link rel="stylesheet" href="css/style.css" />
  7. <title>登录</title>
  8. </head>
  9. <body>
  10. <form action="" onsubmit="return false">
  11. <h2>用户登录</h2>
  12. <input
  13. type="email"
  14. name="email"
  15. placeholder="email@php.cn"
  16. required
  17. autofocus
  18. />
  19. <input
  20. type="password"
  21. name="password"
  22. placeholder="password for php.cn"
  23. required
  24. />
  25. <div>
  26. <input type="text" name="captch" required placeholder="验证码" />
  27. <button type="button">点击获取验证码</button>
  28. <img src="" alt="" />
  29. </div>
  30. <button>登录</button>
  31. </form>
  32. </body>
  33. <script>
  34. ////////////////////////////////////////
  35. // 获取验证码按钮 和 img
  36. var captch_btn = document.querySelector("form > div > button");
  37. var img = document.querySelector("form > div > img");
  38. // 验证码按钮被单击
  39. captch_btn.onclick = function () {
  40. // 隐藏按钮
  41. captch_btn.style.display = "none";
  42. // 显示img
  43. img.style.display = "inline";
  44. // 创建异步请求 请求验证码
  45. var xhr = new XMLHttpRequest();
  46. // 监听请求
  47. xhr.onreadystatechange = function () {
  48. if (xhr.readyState === 4 && xhr.status === 200) {
  49. img.src = xhr.responseText;
  50. }
  51. };
  52. // 初始化请求参数
  53. xhr.open("get", "handle.php?action=captch", true);
  54. // 发送请求
  55. xhr.send(null);
  56. };
  57. // 图片被单击
  58. img.onclick = function () {
  59. // 创建异步请求 请求验证码
  60. var xhr = new XMLHttpRequest();
  61. // 监听请求
  62. xhr.onreadystatechange = function () {
  63. if (xhr.readyState === 4 && xhr.status === 200) {
  64. // 修改src属性
  65. img.src = xhr.responseText;
  66. }
  67. };
  68. // 初始化请求参数
  69. xhr.open("get", "handle.php?action=captch", true);
  70. // 发送请求
  71. xhr.send(null);
  72. };
  73. ///////////////////////////////////////
  74. // 登录按钮被单击
  75. // 获取表单 和按钮
  76. var form = document.querySelector("form");
  77. var btn = document.querySelector("form > button");
  78. // 点击事件
  79. btn.onclick = function () {
  80. // 创建ajax对象
  81. var xhr = new XMLHttpRequest();
  82. // 监听返回数据
  83. xhr.onreadystatechange = function () {
  84. if (xhr.readyState === 4 && xhr.status === 200) {
  85. // 反序列化JSON
  86. var msg = JSON.parse(xhr.responseText);
  87. if (msg.message === 1) {
  88. // 跳转去首页
  89. location.href = msg.href;
  90. } else {
  91. // 创建span标签
  92. var span = document.createElement("span");
  93. // 给个值
  94. span.innerHTML = msg.error;
  95. // 换个颜色
  96. span.style.color = "red";
  97. // 标签插入到form表单中
  98. form.appendChild(span);
  99. }
  100. }
  101. };
  102. // 初始化请求参数
  103. xhr.open("POST", "handle.php?action=login", true);
  104. // 获取到表单数据
  105. var data = new FormData(form);
  106. // 发送请求
  107. xhr.send(data);
  108. };
  109. // 清除一下提示信息
  110. var inputs = document.querySelectorAll("input");
  111. for (var i = 0; i < inputs.length; i++) {
  112. // 当有一个input被选中时
  113. inputs[i].oninput = function () {
  114. // 如果button的后面存在元素
  115. if (btn.nextElementSibling !== null) {
  116. // 先获取到span;
  117. var spans = document.querySelectorAll("span");
  118. for (var i = 0; i < spans.length; i++) {
  119. // 循环删除
  120. form.removeChild(btn.nextElementSibling);
  121. }
  122. }
  123. };
  124. }
  125. </script>
  126. </html>

handle.php

  1. <?php
  2. //先判断请求是否合法
  3. if (!isset($_GET['action'])){
  4. die('非法请求');
  5. }
  6. require 'vendor/autoload.php';
  7. use Gregwar\Captcha\CaptchaBuilder;
  8. //开启session
  9. session_start();
  10. //获取action指令
  11. $action = $_GET['action'];
  12. //执行
  13. switch ($action){
  14. // 验证码
  15. case "captch":
  16. $builder = new CaptchaBuilder(4);
  17. $builder->build();
  18. $_SESSION['phrase'] = $builder->getPhrase();
  19. echo $builder->inline();
  20. break;
  21. // 登录
  22. case 'login':
  23. // 先判断验证码是否正确
  24. if (!stristr($_SESSION['phrase'],$_POST['captch'],false)){
  25. die(json_encode(['message'=>0 , 'error'=> '验证码错误']));
  26. }
  27. // 查找数据库
  28. $pdo = new PDo('mysql:host=localhost;dbname=php11.edu','php11.edu','php11.edu');
  29. $stmt = $pdo->prepare('SELECT * FROM `admin` WHERE `email`=? AND `password` = ?');
  30. $stmt->execute([$_POST['email'],sha1($_POST['password'])]);
  31. $user = $stmt->fetch(PDO::FETCH_ASSOC);
  32. // 判断有没有返回数据
  33. if ($user !== false){
  34. // 有数据创建session
  35. $_SESSION['user'] = serialize($user);
  36. // 序列化返回
  37. echo json_encode(['message'=>1 , 'href'=>'index.php']);
  38. }else{
  39. // 没有数据说明密码或邮箱错误
  40. echo json_encode(['message'=>2 , 'error'=> '邮箱或密码错误']);
  41. }
  42. break;
  43. // 退出
  44. case 'logout':
  45. if (session_destroy()) {
  46. echo '<script>alert("退出成功");location.href="index.php";</script>';
  47. }
  48. break;
  49. }

style.css

  1. * {
  2. margin: 0px;
  3. padding: 0px;
  4. box-sizing: border-box;
  5. }
  6. body {
  7. min-height: 100vh;
  8. min-width: 100vw;
  9. background-color: lightskyblue;
  10. display: flex;
  11. justify-content: center;
  12. align-items: center;
  13. }
  14. form {
  15. width: 400px;
  16. gap: 20px;
  17. display: grid;
  18. padding: 20px;
  19. background-color: #fff;
  20. border: none;
  21. border-radius: 10px;
  22. box-shadow: 1px 1px 5px black;
  23. }
  24. form input {
  25. height: 30px;
  26. border: none;
  27. border: 1px solid #ccc;
  28. border-radius: 3px;
  29. text-indent: 20px;
  30. }
  31. form div {
  32. height: 30px;
  33. display: flex;
  34. justify-content: space-between;
  35. }
  36. form > div > input {
  37. width: 200px;
  38. }
  39. form > div > button {
  40. margin-right: 20px;
  41. width: 120px;
  42. border: none;
  43. padding: 5px;
  44. border-radius: 3px;
  45. background-color: #cfcfcf;
  46. color: red;
  47. }
  48. form > div > button:hover {
  49. background-color: grey;
  50. color: #fff;
  51. }
  52. form > div > img {
  53. margin-right: 20px;
  54. width: 120px;
  55. border-radius: 3px;
  56. display: none;
  57. }
  58. form > button {
  59. height: 30px;
  60. border: none;
  61. background-color: lightseagreen;
  62. color: #fff;
  63. font-size: 1.2rem;
  64. letter-spacing: 20px;
  65. border-radius: 10px;
  66. }
  67. form > button:hover {
  68. background-color: limegreen;
  69. }

关于验证码

  1. composer require gregwar/captcha

7. 总结

本来打算把注册也写上的,写得太慢了,写着写着就六点了,只能用已有的账号密码演示了,删除 span 提示标签时,按教案写法结果为 input 删除一个字,span 删除一条 在里面又加了一个循环完美解决 实现删除一个字,span 全部删除

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议