• Ajax_简介: 异步的 JS 和 XML_原生写 ajax 分析其原理_jquery_ajax_art-template


    AJAX

    Asynchronous JavaScript And XML

    通过 AJAX 可以在 浏览器中向 服务器 发送异步请求

    一种 使用现有标准的 新方法,而非新语言

    • XML 

    可扩展标记语言

    被设计用来传输和存储数据

    被 JSON 替代,JSON 内容更少,解析更方便

    和 HTML 类似,不同的是

    • HTML 都是预定义标签
    • XML 全部是自定义标签,用来表示一些数据
    • AJAX 工作原理

    相当于在 用户 和 服务器 之间加了一个中间层(AJAX 引擎)

    使得 用户操作 和 服务器响应 异步化

    1. 原生 AJAX(不要通过 webstorm 启动页面,否则会发生 跨域 错误)

    // 1. 创建 xhr 对象

    const xhr = new XMLHttpRequest();

    // 2. 设置事件监听

    xhr.onreadystatechange = function(){    // 会监听 readyState 值的变化

    if (xhr.readyState === 2) {

    console.log(xhr.status);
    console.log(xhr.getResponseHeader('Content-Type'));

    }
    if (xhr.readyState === 3) {

    console.log(xhr.responseText);

    }

    if(xhr.readyState === 4 && xhr.status === 200){    // 响应成功

    console.log(xhr.responseText);    // 响应数据

    };

    };

    /****

    前端面试题:

    readyState

    0        xhr 对象创建成功,但是 xhr.open() 还未调用

    1        open() 已经调用了,但是还未调用 send() (意味着还没有发送请求,还可以设置请求头信息)

    2        send() 已经调用了,接收到部分响应数据(响应首行、响应头,没接到响应体)

    3        接收到了响应体数据(如果响应体较小,或者纯文体,在此阶段就全部接收完了)

    4        接收完全部的响应体数据(数据较大,或者音视频资源)

    ****/

    // 3. 设置请求信息    设请求方式、地址、参数

    xhr.open("GET", "http://localhost:3000/ajax?username=jack&age=18");

    // 还能设置请求头 xhr.setRequestHeader();

    xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');

    /****

    必须要设置 请求头 标准规范(有三种常见规范),否则不会解析请求参数

    chrome 和 FireFox    第二次及以后默认走协商缓存,状态码 304,且还会向服务器发送请求

    ie    第二次及以后 get 请求 默认走强制缓存,状态码 200,且不会向服务器发送请求

    需求: 股票 需要实时更新信息,此时就不能从缓存里找

    解决 ie 的缓存问题:

    让每一次的请求不一样

    只要请求不一样,就不会走缓存

    xhr.open("GET", "http://localhost:3000/ajax?username=jack&age=18&date="+Date.now());

    ****/

    // 4. 发送请求

    xhr.send();

    // post 发送数据 必须以 urlencode 格式,即查询字符串去掉?,即 key=value的方式,多个键值对之间以 & 连接

    • 源码实例
    • node.js 服务器

    index.js

    • const express = require('express');
      
      const app = express();
      
      app.use(express.static("public"));
      app.use(express.urlencoded({extended: true}));
      
      app.get("/", (request, response)=>{
          response.sendFile("./public/idnex.html");
      });
      
      // 原生 ajax 的 get 路由
      app.get("/ajax", (request, response)=>{
          console.log('----get 接收的 浏览器数据: ');
          console.log(request.query);    // {}
           console.log(request.body);    // get 请求体 始终为空
           console.log('----');
          
          response.send({name: '服务器 get 响应', line: 15});
      });
      
      // 原生 ajax 的 post 路由
      app.post("/ajax", (request, response)=>{
          console.log('----post 接收的 浏览器数据: ');
          console.log(request.query);    // {} 可以有 请求字符串
           console.log(request.body);    // post请求体 数据{ username: 'jack', age: '18' }
           console.log('----');
          
          response.send({name: '服务器 post 响应', line: 21});
      });
      
      /**************** 端口号 3000, 启动服务器 ***************/
      app.listen(3000, err=>console.log(err?err:'
      
      服务器已启动: http://localhost:3000
      		Hunting Happy!'));
    • 浏览器前端代码

    index.html

    • <!DOCTYPE html>
      <html>
          <head>
              <meta charset="UTF-8"/>
              <title>原生 ajax</title>
          </head>
          
          <body>
              
              <button id="get_btn">get</button>
              <button id="post_btn">post</button>

      <script type="text/javascript" src="js/index.js"></script> </body> </html>

    js/index.js

    • window.addEventListener('DOMContentLoaded', function () {
          const getBtn = document.getElementById("get_btn");
          const postBtn = document.getElementById("post_btn");
          
          getBtn.onclick = function () {
              // 1. 创建 xhr 对象
                 const xhr = new XMLHttpRequest();
              
              // 2. 设置事件监听
                 xhr.onreadystatechange = function () {
                  if (xhr.readyState === 2) {
                      console.log(xhr.status);    // 状态码
                       console.log(xhr.getResponseHeader('Content-Type'));    // 请求头 信息
                  };
                  if (xhr.readyState === 3) {
                      console.log(xhr.responseText);    // 服务器响应 数据
                  };
                  if(xhr.readyState === 4 && xhr.status === 200){
                      console.log(xhr.responseText);    // 服务器响应 数据
                  };
              };
              
              // 3. 设置请求方式、请求地址、请求参数
                 xhr.open("GET", "http://localhost:3000/ajax?username=get&get=get");
          
              // 4. 设置请求头
                 xhr.setRequestHeader('get-x', 'get');    
              
              // 5. 发送请求
                 xhr.send('request=get&get=get');    // get 请求体为空,所以这里传的参数,无效
          };
          
          postBtn.onclick = function () {
              // 1. 创建 xhr 对象
                 const xhr = new XMLHttpRequest();
          
              // 2. 设置事件监听
                 xhr.onreadystatechange = function () {
                  if (xhr.readyState === 2) {
                      console.log(xhr.status);
                      console.log(xhr.getResponseHeader('Content-Type'));
                  }
                  if (xhr.readyState === 3) {
                      console.log(xhr.responseText);
                  }
                  if(xhr.readyState === 4 && xhr.status === 200){
                      console.log(xhr.responseText);
                  };
              };
          
              // 3. 设置请求方式、请求地址、请求参数
                 xhr.open("POST", "http://localhost:3000/ajax?username=post&post=post");
          
              // 4. 设置请求头
                 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');    
              
              // 5. 发送请求
                 xhr.send('request=post&post=post');
          };
      }, false);

    2. jQuery 中的 AJAX 请求

    • node.js 服务器

    index.js

    • const express = require('express');
      
      const app = express();
      
      app.use(express.static("public"));
      app.use(express.urlencoded({extended: true}));
      
      app.get("/", (request, response)=>{
          response.sendFile("./public/idnex.html");
      });
      
      // 原生 ajax 的 get 路由
      app.get("/jquery_ajax", (request, response)=>{
          console.log('----get 接收的 浏览器数据: ');
          console.log(request.query);    // {}
            console.log(request.body);    // get 请求体 始终为空
            console.log('----');
          
          response.send({name: '服务器 get 响应', line: 15});
      });
      
      // 原生 ajax 的 post 路由
      app.post("/jquery_ajax", (request, response)=>{
          console.log('----post 接收的 浏览器数据: ');
          console.log(request.query);    // {} 可以有 请求字符串
            console.log(request.body);    // post请求体 数据{ username: 'jack', age: '18' }
            console.log('----');
          
          response.send({name: '服务器 post 响应', line: 21});
      });
      
      /**************** 端口号 3000, 启动服务器 ***************/
      app.listen(3000, err=>console.log(err?err:'
      
      服务器已启动: http://localhost:3000
      		Hunting Happy!'));
    • 浏览器前端代码

    index.html

    • <!DOCTYPE html>
      <html>
          <head>
              <meta charset="UTF-8"/>
              <title>jQuery 中的 ajax</title>
          </head>
          
          <body>
              
              <button id="get_btn">get</button>
              <button id="post_btn">post</button>
          
              <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
              <script type="text/javascript" src="js/jquery_ajax.js"></script>
          </body>
      </html>

    index.js

    • window.addEventListener('DOMContentLoaded', function () {
          const getBtn = document.getElementById("get_btn");
          const postBtn = document.getElementById("post_btn");
          
          getBtn.onclick = function () {
              $.ajax('http://localhost:3000/jquery_ajax', {
                  method: 'GET',    // 可以直接换成 POST,库解决好了请求头和兼容等一系列问题
                  data: {
                      getrequest:'Browser',
                      age:10
                  },
                  headers: {
                      'get-xxx': 'xxxx'
                  },
                  success: function (server_info) {
                      console.log('请求成功的回调函数');
                      console.log(server_info);    // 自动将 json 字符串 转换成 JSON 对象
                  },
                  error: function (err) {
                      console.log('请求失败的回调函数');
                      console.log(err);
                  }
              });
          };
          
          postBtn.onclick = function () {
              $.get(    // 可以直接换成 post,库解决好了请求头和兼容等一系列问题
                  'http://localhost:3000/jquery_ajax',
                  {postrequest:'Browser', age:26},
                  function (server_info) {
                  console.log(server_info);
              });
          };
      }, false);

    三级联动 选择(省-市-县)

    • 服务器 index.js
    • const express = require('express');
      const promiseConnect = require('./db/connectDB.js');
      const citiesModel = require('./models/userModel.js');
      const app = express();
      
      (async ()=>{
          const ret = await promiseConnect;
          console.log(ret);
          
          app.use(express.static("public"));
          app.use(express.urlencoded({extended: true}));
          
          app.get("/", (request, response)=>{
              response.sendFile("./public/index.html");
          });
      
          // 省 的 get 路由
          app.get("/province", async (request, response)=>{
              try{
                  const province = await citiesModel.find({"level": 1}, {"province": 1, "name": 1, "_id": 0});
                  response.json({code: 200, data: province});
              }catch(err){
                  console.log(err);
                  response.json({code: 404, data: '网络不稳定,请刷新重试'});
              };
          });
          
          // 市 的 get 路由
          app.get("/city", async (request, response)=>{
              try{
                  const {province} = request.query;
                  const city = await citiesModel.find({province, "level": 2}, {"city": 1, "name": 1, "_id": 0});
                  response.json({code: 200, data: city});
              }catch(err){
                  console.log(err);
                  response.json({code: 404, data: '网络不稳定,请刷新重试'});
              };
          });
          
          // 县 的 get 路由
          app.get("/county", async (request, response)=>{
              try{
                  const {province, city} = request.query;
                  const county = await citiesModel.find({province, city, "level": 3}, {"county": 1, "name": 1, "_id": 0});
                  response.json({code: 200, data: county});
              }catch(err){
                  console.log(err);
                  response.json({code: 404, data: '网络不稳定,请刷新重试'});
              };
          });
      })().catch(err=>console.log(err));
      
      /**************** 端口号 3000, 启动服务器 ***************/
      app.listen(3000, err=>console.log(err?err:'
      
      服务器已启动: http://localhost:3000
      		Hunting Happy!'));
    • 浏览器前端 index.html
    • <!DOCTYPE html>
      <html>
          <head>
              <meta charset="UTF-8"/>
              <title>三级联动-省-市-县</title>
              <link rel="stylesheet" href="./css/index.css">
          </head>
          
          <body>
              <div id="outer_box">
                  <select id="province">
                      <option>请选择省份</option>
                  </select><select id="city">
                      <option>请选择市</option>
                  </select><select id="county">
                      <option>请选择区(县)</option>
                  </select>区(县)
              </div>
              
              
              
              <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
              <script type="text/javascript" src="./js/jquery_ajax.js"></script>
          </body>
      </html>

    index.css

    • html, body {
          width: 100%;
          height: 100%;
          
          color: #000;
          background: #b9c2a4;
          background-size: cover; /* 指定背景图片大小 */
      }
      
      /*************************************************/
      #outer_box {
          width: 100%;
          height: 100%;
          display: flex;
          justify-content: center;
          align-items: center;
      }
      
      #outer_box select {
          width: 152px;
          font-size: 16px;
          background-color: #aec57e;
          cursor: pointer;
      }
    • 选择省份

    为了避免重排 重绘,使用拼串,最后一次追加

    • 选择市

    监听 表单的 change 事件

    • 选择县
    • jquery_ajax.js
    • $(function () {
          const $province = $("#province");
          const $city = $("#city");
          const $county = $("#county");
          
          // 进入页面 首先渲染省份
          $.get("http://localhost:3000/province", function({code, data}){
              if(code === 200){
                  let htmlStr = '<option>请选择省份</option>';
                  data.forEach(each=>{
                      /* <option value="44">广东省</option> */
                      htmlStr += `<option value="${each.province}">${each.name}</option>`;
                  });
                  $province.html(htmlStr);
              }else{
                  alert(data);    // 网络不稳定,请刷新重试
              };
          });
          
          // 省 改变出现 市
          $province.on("change", function(){
              const province = this.value;    /* <option value="11">北京</option> */
              $.get('/city', {province}, function({code, data}){
                  if(code === 200){
                      let htmlStr = '<option>请选择市</option>';
                      data.forEach(each=>{
                          /* <option value="03">深圳市</option> */
                          htmlStr += `<option value="${each.city}">${each.name}</option>`;
                      });
                      $city.html(htmlStr);
                  }else{
                      alert(data);    // 网络不稳定,请刷新重试
                  };
              });
          });
          
          // 市 改变出现 县
          $city.on("change", function(){
              const province = $province.val();    /* <option value="11">北京</option> */
              const city = $city.val();    /* <option value="undefined">鞍山市</option> */
              console.log({province, city});
              $.get('/county', {province, city}, function({code, data}){
                  if(code === 200){
                      let htmlStr = '<option>请选择市</option>';
                      data.forEach(each=>{
                          /* <option value="06">宝安区</option> */
                          htmlStr += `<option value="${each.county}">${each.name}</option>`;
                      });
                      $county.html(htmlStr);
                  }else{
                      alert(data);    // 网络不稳定,请刷新重试
                  };
              });
          });
      });

    在 jQuery 中 $.get("http://localhost:3000/city", function({code, data}){}); 对于同一域名,可以简写为

    • $.get("/city", function({code, data}){});

    1. 引入 第三方 js库 art-template

    <script type="text/javascript" src="./js/template-web.js"></script>

    2. 新建 <script> 标签,并设置 id 以供渲染

    3. 

    源码由上方代码改变

    • index.html
    • <!DOCTYPE html>
      <html>
          <head>
              <meta charset="UTF-8"/>
              <title>jQuery 中的 ajax</title>
              <link rel="stylesheet" href="./css/index.css">
          </head>
          
          <body>
              <div id="outer_box">
                  <select id="province">
                      <option>请选择省份</option>
                  </select>省
              
                  <select id="city">
                      <option>请选择市</option>
                  </select>市
              
                  <select id="county">
                      <option>请选择区(县)</option>
                  </select>区(县)
              </div>
          
              <script type="text/html" id="templateScript">
                  <option>{{firstOption}}</option>
              {{each data}}
                  <option value="{{$value[name]}}">{{$value.name}}</option>
              {{/each}}
              </script>
              
              
              
              
              <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
              <script type="text/javascript" src="./js/template-web.js"></script>
              <script type="text/javascript" src="./js/jquery_ajax.js"></script> <!-- 注意编写顺序 -->
          </body>
      </html>
    • jquery_ajax.js
    • $(function () {
          const $province = $("#province");
          const $city = $("#city");
          const $county = $("#county");
          
          // 进入页面 首先渲染省份
          $.get("http://localhost:3000/province", function({code, data}){
              if(code === 200){
                  const htmlStr = template(
                      'templateScript',
                      {data, firstOption: '请选择省份', name: 'province'}
                  );
                  $province.html(htmlStr);
              }else{
                  alert(data);    // 网络不稳定,请刷新重试
              };
          });
          
          // 省 改变出现 市
          $province.on("change", function(){
              const province = this.value;    /* <option value="11">北京</option> */
              $.get('/city', {province}, function({code, data}){
                  if(code === 200){
                      const htmlStr = template(
                          'templateScript',
                          {data, firstOption: '请选择市', name: 'city'}
                      );
                      $city.html(htmlStr);
                  }else{
                      alert(data);    // 网络不稳定,请刷新重试
                  };
              });
          });
          
          // 市 改变出现 县
          $city.on("change", function(){
              const province = $province.val();    /* <option value="11">北京</option> */
              const city = $city.val();    /* <option value="undefined">鞍山市</option> */
              $.get('/county', {province, city}, function({code, data}){
                  if(code === 200){
                      const htmlStr = template(
                          'templateScript',
                          {data, firstOption: '请选择区县', name: 'county'}
                      );
                      $county.html(htmlStr);
                  }else{
                      alert(data);    // 网络不稳定,请刷新重试
                  };
              });
          });
      });

     

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    通过注册表设置指定用户启动项的权限
    音频知识学习
    回老家也不忘老本......
    探索DOMNode
    表单填写示例(通过JavaScript访问DOM)
    最近的一些感悟
    C#和Java中的Substring()
    验证ASP.NET页生命周期时间的触发顺序
    解析c语言背后的汇编代码
    oracle nvl()函数在使用中出现的问题
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/10169234.html
Copyright © 2020-2023  润新知