Loading...
墨滴

就到这里吧

2021/05/05  阅读:47  主题:全栈蓝

AJAX

AJAX

优点

  1. 无需刷新网页与服务器通信
  2. 允许用户事件更新部分页面内容

缺点

  1. 没有浏览记录,不能回退
  2. 存在跨域问题(同源)
  3. SEO不友好(搜索引擎优化)

express基本使用

安装

在当前文件夹下 open in terminal

node init --yes
node i express

创建

//1、引入express
const express = require('express')

//2、创建应用对象
const app = express()

//3、创建路由规则
//request 是对请求报文的封装
//response是对响应报文的封装
app.get('/', (req, res) => {
//设置响应
 res.send("hello express")
});

//4、监听端口启动服务
app.listen(8000, () => {
 console.log("服务已经启动,8000端口监听中")
})

测试

GET请求

server.js

//1、引入express
const express = require("express");

//2、创建应用对象
const app = express();

//3、创建路由规则
//request 是对请求报文的封装
//response是对响应报文的封装
app.get("/server", (req, res) => {
 //设置响应 设置允许跨域
 res.setHeader("Access-Control-Allow-Origin""*");
 //设置响应体
 res.send("Hello AJAX");
});

//4、监听端口启动服务
app.listen(8000, () => {
 console.log("服务已经启动,8000端口监听中");
});

html页面

  <script>
   const btn = document.querySelector("button");
   const show = document.querySelector(".show");
   btn.addEventListener("click"function ({
    //1、创建对象
    const xhr = new XMLHttpRequest();
    // 2、初始化 设置请求方法和url
    xhr.open("GET""http://localhost:8000/server");
    // 3、发送
    xhr.send();
    // 4、事件绑定 处理服务端返回的结果
    // readystate 是xhr对象的属性 表示状态 0 1 2 3 4
    xhr.onreadystatechange = function ({
     //判断(服务器返回的所有结果)
     if (xhr.readyState === 4) {
      // 判断响应状态码 200 404 401 500
      // 2xx 成功
      if (xhr.status >= 200 && xhr.status < 300) {
       //处理结果 行 头 空 体
       //1响应行
       console.log(xhr.status);//状态码
       console.log(xhr.responseText);//响应字符串
       console.log(xhr.getAllResponseHeaders());//所有响应头
       console.log(xhr.response);//响应体
       show.insertAdjacentHTML("afterbegin", xhr.response);
      } else {

      }
     }
    };
   });
  </script>

POST请求

server.js

app.post("/server", (req, res) => {
 res.setHeader("Access-Control-Allow-Origin""*");
 //响应头
 res.setHeader("Access-Control-Allow-Headers""*");
 res.send("Hello AJAX POST");
});

html

    //1、创建对象
    const xhr = new XMLHttpRequest();
    //2、初始化设置类型与URL
    xhr.open("POST""http://localhost:8000/server");
    //设置请求头
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
    //自定义属性
    xhr.setRequestHeader('username','chunxi')
    //3、发送
    xhr.send('a=1&b=2&c=3')
    // xhr.send('a:1&b:2&c:3')
    // xhr.send('sakura')
    // xhr.send();
    // 4、事件绑定
    xhr.onreadystatechange = () => {
     if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
       this.innerHTML = xhr.response;
      }
     }
    };

自定义请求头属性需要在server端设置对应的接收

server.js

//接收任意请求
app.all("/server", (req, res) => {
 res.setHeader("Access-Control-Allow-Origin""*");
 //响应头 接收任意
 res.setHeader("Access-Control-Allow-Headers""*");
 res.send("Hello AJAX POST");
});

发送json数据

手动转换

server.js

//接收任意请求
app.all("/server", (req, res) => {
 res.setHeader("Access-Control-Allow-Origin""*");
 //响应头 接收任意
 res.setHeader("Access-Control-Allow-Headers""*");
 //响应一个json数据
 const data ={
  name:chunxi,
  age:18
 }
 let str = JSON.stringify(data)
 res.send(str)
 // res.send("Hello AJAX POST");
});

html

   xhr.onreadystatechange = () => {     
        if (xhr.readyState === 4) {      
          if (xhr.status >= 200 && xhr.status < 300) {       
            //手动对数据进行转换       
            let data = JSON.parse(xhr.response)       
            this.innerHTML=`${data.name}==>${data.age}`       
            // this.innerHTML = xhr.response;     
          }     
        }   
      };

自动转换

html

//1、创建对象
const xhr = new XMLHttpRequest();
//设置响应头数据类型
xhr.responseType = "json"
xhr.onreadystatechange = () => { 
  if (xhr.readyState === 4) {  
    if (xhr.status >= 200 && xhr.status < 300) {   
      //手动对数据进行转换   
      // let data = JSON.parse(xhr.response)   
      // this.innerHTML=`${data.name}==>${data.age}`   
      console.log(xhr.response);   
      // this.innerHTML = xhr.response;  
    }
  }
};

nodemon

快速启动server 只要server修改就自动重新启动

安装

sudo npm install -g nodemon

重新启动server

 nodemon server.js    

正常访问

IE缓存问题

对于ie浏览器 加载过的ajax请求会被缓存,服务端修改后 ie会直接在缓存中寻找ajax请求而不是再次发起请求 导致页面数据并未被修改

解决方法

xhr.open("GET""http://localhost:8000/ie-server?t=" + Date.now());

给每次请求添加一个时间戳

请求超时与网络异常

设置请求超时

html

const xhr = new XMLHttpRequest();
//设置2000ms超时xhr.timeout = 2000;
xhr.open("get""http://127.0.0.1:8000/delay");
xhr.send();
xhr.onreadystatechange = function (
  if (xhr.readyState === 4) {  
    if (xhr.status >= 200 && xhr.status < 300) {   
      result.innerHTML = xhr.response  
    } 
  }
};

server.js

//延时响应
app.get("/delay", (req, res) => {   
  //设置响应 设置允许跨域   
  res.setHeader("Access-Control-Allow-Origin""*");   
  //设置响应体   setTimeout(() => {      
  res.send("延时响应");   
  }, 3000);
});

设置超时回调函数

const xhr = new XMLHttpRequest();
//设置2000ms超时 取消请求
xhr.timeout = 2000;
//超时回调
xhr.ontimeout = function (
  alert("网络异常,请稍后重试!!");
};
xhr.open("get""http://127.0.0.1:8000/delay");
xhr.send();
xhr.onreadystatechange = function (
  if (xhr.readyState === 4) {  
    if (xhr.status >= 200 && xhr.status < 300) {   
      result.innerHTML = xhr.response;  
    } 
  }
};

网络异常回调

//网络异常回调
xhr.onerror = function ()
  alert("你的网线被拔了!!!");
}

取消请求

可以在发送请求后 手动取消请求

const btns = document.getElementsByTagName("button");
let xhr = null;
btns[0].onclick = function ()
  xhr = new XMLHttpRequest() 
  xhr.open('get','http://localhost:8000/delay'
  xhr.send()
}
btns[1].onclick=function (){  
  //取消请求  
  xhr.abort()
}

重复请求问题

通过添加一个布尔值 判断用户是否已经发起过请求,始终保持用户发送一个ajax请求

const btns = document.getElementsByTagName("button");
let xhr = null;
let isSending = false;
btns[0].onclick = function (
  if (isSending) xhr.abort(); //如果正在发送则取消该请求,创建一个新的ajax请求 
  xhr = new XMLHttpRequest();
  isSending = true
  xhr.open("get""http://localhost:8000/delay"); 
  xhr.send(); 
  xhr.onreadystatechange = function ({  
    if (xhr.readyState === 4) {   
      isSending = false;  
    } 
  };
};

jQuery 发送AJAX请求

html

<div class="container"> 
  <h2>jQuery发送AJAX请求</h2> 
  <button type="button" class="btn btn-danger">GET</button> 
  <button type="button" class="btn btn-warning">POST</button> 
  <button type="button" class="btn btn-info">普通AJAX</button>
</div>
/** 
  * 参数1:url 
  * 参数2:请求参数 
  * 参数3:回调函数 
  * 参数4:响应体数据类型 
  */

$('button').eq(0).click(function ()
  $.get('http://localhost:8000/jquery',{a:100,b:200},function (data){  
    console.log(data); 
  },'json')
});
$("button").eq(1).click(function (
  $.post("http://localhost:8000/jquery"
    {a100b200}, 
    function (data{  
      console.log(data); 
    });
});

server.js

//jquery
app.all("/jquery", (req, res) => {   
  //设置响应 设置允许跨域   
  res.setHeader("Access-Control-Allow-Origin""*");   
  // res.send("hello jquery ajax")   
  const data = {      
    name"Saber",      
    age18   
  };   
  res.send(JSON.stringify(data));
});

加了响应体数据类型的返回的是json格式,没加的是字符串

通用方法

$("button").eq(2).click(function ({
    $.ajax({
     url:"http://localhost:8000/jquery",
     data:{
      name:"Archer",
      age:20
     },
     type:"GET",
     dataType:"json",
     success:function (data){
      console.log(data);
     },
     //失败回调
     error:function (){
      console.log("出错啦!!!");
     },
     //响应头
     //如需自定义 需在server端设置(请查看之前的设置)
     header:{
      name"Rider",
      age16
     }
    });
   });

axios发送AJAX请求

GET

   const btns = document.querySelectorAll("button");

   //配置baseURL
   axios.defaults.baseURL = "http://localhost:8000";
   btns[0].onclick = function ({
    //get请求
    axios.get("/axios", {
     //url参数
     params: {
      id100,
      name"Caster"
     },
     //请求头信息
     headers: {
      name"Lancer",
      age30
     }
    }).then(value => {
     console.log(value);
    });
   };

POST

btns[1].onclick = function ({
    //参数 url,data,config
    axios.post("/axios", {
     username"Saber",
     password"你就是老子的maser吗"
    }, {
     params: {
      height180,
      weight160,
      xxx18
     },
     headers: {
      name"gold light"
     }
    }).then(value => {
     console.log(value);
    });
   };

通用方式

btns[2].onclick = function (){
    axios({
     method:"POST",
     url:"/axios",
     params:{
      id:1001,
      name:'史莱姆'
     },
     headers:{
      skill:"eat"
     },
     data:{
      username'admin',
      password'admin123'
     }
    }).then(response => {
     console.log(response);
     //响应状态码
     console.log(response.status);
     //响应状态字符串
     console.log(response.statusText);
     //响应状态头信息
     console.log(response.headers);
     //响应体
     console.log(response.data);
    })
   }

fetch发送AJAX请求

 const btn = document.querySelector("button");
   btn.onclick = function ({
    fetch("http://localhost:8000/fetch?name=张三", {
         //请求方法
         method"post",
         // 请求头
         headers: {
          username"zhangsan"
         },
         // 请求体
         body"password=141414&age=30"
        }
    ).then(response => {
     // 返回文本
     // return response.text();
     // 返回json
     return response.json();
    }).then(response => {
     console.log(response);
    });
   };

同源策略

同源策略是浏览器的一种安全策略,由netscape公司提出

同源:协议、域名、端口号 必须完全相同

违背同源策略就是跨域

JSONP

原理

  <script>
   function handle(data{
    const result = document.querySelector("#result");
    result.innerHTML = data.name;
    console.log(data);
   }
  
</script>
  <script src="http://localhost:9000/jsonp"></script>

利用script标签会加载JavaScript代码

server.js

app.all("/jquery-jsonp", (req, res) => {
 const data = {
  servant"Saber",
  master"weigongshilang"
 };
 let str = JSON.stringify(data);
 let cb = req.query.callback
 res.end(`${cb}(${str})`);
});

实践

const input = document.querySelector("input");
   const p = document.querySelector("p");

   function handle(data){
    p.innerHTML = data.msg
    console.log(data);
   }

   input.onblur = function ({
    let username = this.value;
    let script = document.createElement("script");
    script.src = "http://localhost:9000/jsonp";
    document.body.appendChild(script);
   };

server.js

app.all("/jsonp", (req, res) => {
 const data = {
  exist1,
  msg"用户名已存在"
 };
 let str = JSON.stringify(data);
 res.end(`handle(${str})`);
});

jQuery 发送jsonp请求

 $("#btn").click(function ({
    //callback必须加
    $.getJSON("http://localhost:9000/jquery-jsonp?callback=?"function (data{
     $("#result").html(`
       从者:${data.servant} <br>
       御主:${data.master}
     `
);
    });
   });

server.js

app.all("/jquery-jsonp", (req, res) => {
 const data = {
  servant"Saber",
  master"weigongshilang"
 };
 let str = JSON.stringify(data);
 let cb = req.query.callback
 res.end(`${cb}(${str})`);
});

CORS

MDN参考

html

const btn = document.querySelector("button");
const result = document.querySelector("#result");

btn.onclick = function ({
 let xhr = new XMLHttpRequest();
 xhr.open("get""http://localhost:9000/cors");
 xhr.send();
 xhr.onreadystatechange = function ({
  if (xhr.readyState === 4) {
   if (xhr.status >= 200 && xhr.status < 300) {
    console.log(xhr.response);
    result.innerHTML = xhr.response
   }
  }
 };
};
app.all("/cors", (req, res) => {
 //允许跨域
 res.setHeader("Access-Control-Allow-Origin""*");
 res.setHeader("Access-Control-Allow-Headers""*");
 res.setHeader("Access-Control-Allow-Method""*");
 res.send("hello cors");
});

就到这里吧

2021/05/05  阅读:47  主题:全栈蓝

作者介绍

就到这里吧