Ajax

 

Ajax

一,定义

概念:

​ AJAX (阿贾克斯 Asynchronous Javascript And Xml ) 异步 JavaScript 和 XML,是指一种创建交互式网页应用的网页开发技术,能发送 HTTP 请求和接收 HTTP 响应;

特点:

​ 1,默认是异步执行

​ 2,能够实现局部刷新

​ 3,不能直接跨域请求

二,浏览器的同源政策:

1,为什么会有?

​ 出于安全性的考虑而制定的安全策略,它只允许对应的两者是同源的内容进行访问和交互;不同源的内容不允许访问;

2,什么是同源?

​ 如果两个 地址 URL 的 (协议)protocolport(端口,如果有指定的话)host(主机/域名)都相同的话,则这两个 URL 是同源

3,什么情况下会触发同源政策,导致无法访问的跨域问题?

​ 异步请求-Ajax;

4,解决跨域问题的方式

​ a,JSONP(非官方跨域数据交互协议);前端

​ b,由服务器端支持跨域,添加请求头(xml.setRequestHeader);后端

​ c, 服务器代理 前端常见使用 nodejs 的代理;

状态码:

​ 0: 请求未初始化   1: 服务器连接已建立   2: 请求已接收   3: 请求处理中   4: 请求已完成,且响应已就绪

响应码:

​ 1xx 信息响应   2xx 成功响应 200   3xx 重定向 304   4xx 客户端错误 404   5xx 服务端错误

三,实现流程

1,创建 Ajax 请求对象

//兼容写法
function createXHR() {
  //IE7+ 谷歌, 火狐, Safari等
  if (window.XMLHttpRequest) {
    return new XMLHttpRequest();
  }
  return new ActiveXObject("Microsoft.XMLHTTP"); //IE6
}

//创建对象
let xml = createXHR();

2,初始化请求,设置请求地址

//请求方式:get,post;   地址:服务器地址;  执行方法:true:异步,false:同步;
xml.open(请求方式地址执行方法);

3,设置监听

xml.onreadyStatechange = function () {
  //判断是否成功请求
  if (xml.readyState == 4 && /^2\d/.test(xml.status)) {
    console.log(xml.response);
    //接收响应的主体
  }
};

4,发送请求

xml.send();

5,接收响应

xml.response();

6,POST 方式的响应头设置

//设置请求头的类型,注意第二个参数, / 后面是发送过去的类型,一般是如下表单类型
xml.setRequestHeader(
  "content-type",
  "application/x-www-form-urlencoded; charset=utf-8"
);

7,请求数据存放的位置

//采用GET方法的,存放在  xml.open()里;
xml.open(请求方式地址?数据请求执行方法);
//在地址后用 ? 连接,后接数据,数据内容使用键值对,不同键值对使用 & 连接;
xml.open("GET","https://jsonplaceholder.typicode.com/todos?uname=l&upwd=123")

//采用POST方法的,存放在  xml.send()里;
xml.send(数据);
//在括号内直接写数据,数据内容使用键值对,不同键值对使用 & 连接;
xml.send("uname=l&upwd=123")

四,Ajax 属性和方法

1,监听:.onreadyStatechange

xml.onreadyStatechange = function () {
  //该方法会在 XMLHttpRequest 的 readyState 属性发生改变时触发
};

五,ASONP 方法解决跨域问题

JSONP(非官方跨域数据交互协议);

1,实现的简述原理:使用 script 的 src 引入需要访问的地址,它使用的是 get 请求;

2,实现过程:

​ a,封装回调函数;b,将函数添加到 windwon 方法;c,使用 script 引入目标地址;

3,JSONP 的封装(使用过 promis)

function jsonp({
  url, //链接地址
  callback, //回调函数的参数名
  param, //参数
}) {
  return new Promise((resolve, reject) => {
    //创建函数名,要随机但必须要以字母开头
    let fnName = "fn" + Date.now() + parseInt(Math.random() * 1000);

    //将函数名和函数设置为window的方法
    //使用promise封装,成功时直接返回
    window[fnName] = resolve;
    //首先创建script标签
    let js = document.createElement("script");
    //将回调函数名和回调函数加到url里
    url += `?${callback}=${fnName}`;
    //设置参数,加入到地址里
    let paramValue = "";
    for (let key in param) {
      paramValue += `&${key}=${param[key]}`;
    }
    url += paramValue;
    //最后设置参数加入到script中
    js.src = url;
    document.body.appendChild(js);

    //优化,加载完成后删除
    js.onload = function () {
      js.remove();
      delete window[fnName];
    };

    //加载失败时,出错的状态
    js.onerror = () => reject("加载错误");
  });
}

4,案例:使用 JSONP 和接口实现百度搜素框效果

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <!--引入已经封装好的JSONP函数-->
    <script src="./jsonp.js"></script>
    <input type="text" id="ipt" />
    <ul id="box"></ul>
    <button id="btn">搜索</button>

    <script>
      //获取元素
      let box = document.getElementById("box");
      let inp = document.getElementById("ipt");
      let li;
      inp.onkeyup = chock(function () {
        //如果input里没有内容则清除所有
        if (inp.value.trim() == "") {
          box.remove();
          return;
        }
        //处理列表框
        box.remove();
        box = document.createElement("ul");
        document.body.appendChild(box);
        //数据处理
        jsonp({
          url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
          callback: "cb",
          param: {
            wd: inp.value,
          },
        }).then((res) => {
          //使用promise.then方法,返回成功的结果;
          if (res != null) {
            for (let i of res.s) {
              li = document.createElement("li");
              li.innerText = i;
              box.appendChild(li);
            }
            //点到哪个,把哪个的内容赋予第一个input
            let list = document.querySelectorAll("li");
            for (let v of list) {
              v.onclick = function () {
                for (let i = 0; i < list.length; i++) {
                  list[i].style.background = "";
                }
                this.style.background = "red";
                inp.value = this.innerText;
              };
            }
          }
        });
      }, 200);

      //点击btn时,获取input里的内容进行搜索
      btn.onclick = function () {
        let text = inp.value;
        console.log(text);
      };

      //节流
      function chock(fn, wait) {
        let timer = null;
        return function () {
          if (timer) return;
          timer = setTimeout(() => {
            fn();
            timer = null;
          });
        };
      }
    </script>
  </body>
</html>