JS-AJAX

AJAX简介

AJAX全称为Asynchoronous JavaScript And XML,就是异步的JS和XML

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

最大的优势:无刷新获取数据

XML简介

XML可扩展标记语言

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

XML和HTML类似,不同的是HTML都是预定义标签,XML没有预定义标签,都是自定义标签

被JSON取代了{"name":"孙悟空",“age”:18,"gender":"男"}

AJAX特点

优点:可以无需刷新页面与服务器端通信;允许根据用户事件来更新部分页面内容

缺点:没有浏览历史,不能回退;存在跨域问题(同源);SEO(搜索引擎优化)不友好

HTTP协议

超文本传输协议,协议详细规定了浏览器和万维网服务器之间的互相通信规则

请求报文

行:请求类型POST  / URL路径  / HTTP/1.1版本

头: Host:aiguigu.com
        Cookie:name = guigu
        Content-type:application/x-www-form-urlencoded
        User-Agent:chrome 83

空行

体:GET的话请求体是空的,POST可以不为空
        username=admin&password=admin

响应报文

行:HTTP/1.1版本   200响应状态码  ok响应状态字符串

头:Content-type:text/html;charset=ytf-8
        Content-length:2048
        Content-encoding:gzip

空行

体:<html><head></head><body><h1>123</h1></body></html>

express基本使用

1.引入express

const express = require('express');

2.创建应用对象

const app = express();

3.创建路由规则

request是对请求报文的封装

response是对响应报文的封装

app.get('/',(request,response) => {

  //设置响应

  response.send('HELLO EXPRESS');

});

4.监听端口启动服务

app.listen(8000,() => {

  console.log('服务已经启动,8000端口监听中')

})

原生AJAX

GET.html

<!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>AJAX GET</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px purple;
    }
  </style>
</head>
<body>
  <button>点击发送请求</button>
  <div id="result"></div>
</body>
<script>
  const btn = document.getElementsByTagName('button')[0];
  const result = document.getElementById('result')
  btn.onclick = function() {
    //1.创建对象
    const xhr = new XMLHttpRequest()
    //2.初始化 设置请求的方法和url
    xhr.open('GET','http://127.0.0.1:8000/server?a=100&b=200&c=300');
    //3.发送
    xhr.send();
    //4.事件绑定 处理服务端返回的结果
    //on:when 当...时候
    //readystate 是xhr对象中的属性,表示状态0 1 2 3 4
    //0表示为初始化,1表示open方法调用完毕,2表示send调用完毕 3表示服务端返回了部分的结果 4表示服务端返回所有结构
    //change 改变
    xhr.onreadystatechange = function() {
      //判断(服务端返回了所有的结果)
      if(xhr.readyState === 4) {
        //判断响应状态码
        if(xhr.status >= 200 && xhr.status <= 300) {
          //处理结果:行、头、空行、体
          //响应行
          console.log(xhr.status); //状态码
          console.log(xhr.statusText);//状态字符串
          console.log(xhr.getAllResponseHeaders()); //所有响应头
          console.log(xhr.response);//响应体

          result.innerHTML = xhr.response;
        } else {

        }
      }
    }
  }
</script>
</html>

POST.html

<!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>AJAX POST</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px purple;
    }
  </style>
</head>
<body>
  <div id="result"></div>
</body>
<script>
  const result = document.getElementById('result');
  result.addEventListener('mouseover',function() {
    //1.创建对象
    const xhr = new XMLHttpRequest();
    //2.初始化 设置类型与URL
    xhr.open('POST','http://127.0.0.1:8000/server')
    //3.发送
    xhr.send()
    //4.事件绑定
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        if(xhr.status >= 200 && xhr.status < 300) {
          //处理服务端返回结果
          result.innerHTML = xhr.response
        }
      }
    }
  })
</script>
</html>

server.js

//1.引入express
const express = require('express');

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

//3.创建路由规则
//request是对请求报文的封装
//response是对响应报文的封装
//server:如果请求行的第二段内容的路径是'/server'的话,就会执行这个回调函数里的代码
//并且由response设置响应
app.get('/server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')

  //设置响应体
  response.send('HELLO AJAX');
});

app.post('/server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')

  //设置响应体
  response.send('HELLO AJAX post');
});

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

POST+参数+请求头.html

<!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>AJAX POST</title>
  <style>
    #result {
      width: 200px;
      height: 100px;
      border: solid 1px purple;
    }
  </style>
</head>
<body>
  <div id="result"></div>
</body>
<script>
  const result = document.getElementById('result');
  result.addEventListener('mouseover',function() {
    //1.创建对象
    const xhr = new XMLHttpRequest();
    //2.初始化 设置类型与URL
    xhr.open('POST','http://127.0.0.1:8000/server')
    //设置请求头
    //Content-Type 设置请求体内容的类型
    //application...参数查询字符串类型的固定写法
    xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
    xhr.setRequestHeader('name','admin')
    //3.发送
    // xhr.send('a=100&b=200')
    xhr.send('a:100&b:200')
    //4.事件绑定
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        if(xhr.status >= 200 && xhr.status < 300) {
          //处理服务端返回结果
          result.innerHTML = xhr.response
        }
      }
    }
  })
</script>
</html>

server.js

//post -> all (all可以接受任意类型的请求)
app.all('/server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')
  //设置请求头信息,一般会把用户身份校验信息放在头信息里边
  //允许前端自定义响应头
  response.setHeader('Access-Control-Allow-Headers','*')

  //设置响应体
  response.send('HELLO AJAX post');
});

json.html

xhr.responseType = 'json'
    //初始化
    xhr.open('GET','http://127.0.0.1:8000/json-server');
    //发送
    xhr.send()
    //事件绑定
    xhr.onreadystatechange = function() {
      if(xhr.readyState === 4) {
        if(xhr.status >= 200 && xhr.status<300) {
          //
          // console.log(xhr.response);
          // result.innerHTML = xhr.response
          //1.手动转换数据
          // let data = JSON.parse(xhr.response)
          // result.innerHTML = data.name
          //2.自动转换 xhr.responseType = 'json'
          result.innerHTML = xhr.response.name

server.js

app.all('/json-server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')
  //设置请求头信息,一般会把用户身份校验信息放在头信息里边
  //允许前端自定义响应头
  response.setHeader('Access-Control-Allow-Headers','*')
  //响应一个数据
  const data = {
    name:'sun'
  }
  //对对象进行字符串转换
  let str = JSON.stringify(data);
  //设置响应体
  response.send(str);
});

IE浏览器的缓存问题

.html

xhr.open('GET','http://127.0.0.1:8000/ie?t='+Data.now())

每次时间戳都不一样所以此时不会走缓存

请求超时与网络异常

.html

const btn = document.getElementsByTagName('button')[0];
  const result = document.getElementById('result')
  btn.onclick = function() {
    const xhr = new XMLHttpRequest();
    //超时设置
    xhr.timeout = 2000;
    //超时回调
    xhr.ontimeout = function() {
      alert('网络异常,请稍后')
    }
    //网络异常回调
    xhr.onerror = 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
        }
      }
    }
  }

server.js

app.all('/delay',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')
  setTimeout(() => {
    response.send('延时响应');
  },2000)
  //设置响应体
});

取消请求

前端调用 xhr.abort()  方法

重复请求问题

让始终只有一个请求在发送

.html

 btns[0].addEventListener('click',function() {
    //判断标识变量
    if(isSending) x.abort() //如果正在发送则取消该请求创建新的
    x = new XMLHttpRequest()
    //修改标识变量的值
    isSending = true
    x.open('GET','http://127.0.0.1:8000/delay')
    x.send();
    x.onreadystatechange = function() {
      if(x.readyState === 4) {
        isSending = false
      }
    }
  })

jQuery中的AJAX

get和post

client.html

<script>
  $('button').eq(0).click(function() {
    $.get('http://127.0.0.1:8000/jquery-server',{a:100,b:200}, function(data) {
      console.log(data);
    },'json');
  })

  $('button').eq(1).click(function() {
    $.post('http://127.0.0.1:8000/jquery-server',{a:100,b:200}, function(data) {
      console.log(data);
    });
  })
</script>

server.js

//jQuery服务
app.all('/jquery-server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')
  const data = {name:'sun'};
  response.send(JSON.stringify(data));  
});

ajax

client.html

$('button').eq(2).click(function() {
    $.ajax({
      //url
      url:'http://127.0.0.1:8000/jquery-server',
      //参数
      data:{a:100,b:200},
      //请求类型
      type:'GET',
      //响应体结果设置
      dataType:'json',
      //成功的回调
      success:function(data) {
        console.log(data)
      },
      //超时时间
      timeout:3000,
      //失败回调
      error:function() {
        console.log('超时了');
      },
      //头信息
      headers: {
        c:300,
        d:400,
      }
    })

server.js

app.all('/jquery-server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')
  //允许前端自定义响应头
  response.setHeader('Access-Control-Allow-Headers','*')
  const data = {name:'sun'};
  response.send(JSON.stringify(data));  
  // response.send('AJAX');  
});

axios

client.html

<!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">
  <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.25.0/axios.js"></script>
  <title>axios 中的AJAX</title>
</head>
<body>
  <button>GET</button>
  <button>POST</button>
  <button>AJAX</button>
</body>
<script>
  const btns = document.querySelectorAll('button')

  axios.defaults.baseURL = "http://127.0.0.1:8000"

  btns[0].onclick = function() {
    //GET请求
    axios.get('/axios-server',{
      //url参数
      params: {
        id:100,
        vip:7,
      },
      //请求头信息
      headers: {
        name:'sun',
        age:6
      }
    }).then(value => {
      console.log(value);
    });
  }

  btns[1].onclick = function() {
    axios.post('/axios-server',{
        username:'admin',
        password:'admin'
    },
      {
      //url
      params: {
        id:200,
        vip:9
      },
      //请求头信息
      headers: {
        height:100
      },
     

    })
  }

</script>
</html>

server.js

//axios服务
app.all('/axios-server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')
  //允许前端自定义响应头
  response.setHeader('Access-Control-Allow-Headers','*')
  // const data = {name:'sun'};
  // response.send(JSON.stringify(data));  
  response.send('axios');  
});

axios自己的方法

.html

btns[2].onclick = function() {
    axios({
      //请求方法
      methods: 'POST',
      //url
      url:'/axios-server',
      params: {
        vip:10,
        level:30
      },
      headers: {
        a:100,
        b:200
      },
      data: {
        username:'admin'
      }
    }).then(response => {
      console.log(response);
      console.log(response.status);
      console.log(response.statusText);
    })
  }

fetch

是一个全局对象,可以直接调用,返回结果是promise对象

btn.onclick = function() {
    fetch('http://127.0.0.1:8000/fetch-server', {
      //请求方法
      method:'POST',
      //请求头
      headers: {
        name:'sun'
      },
      //请求体
      body: 'username=admin&password=admin'

    }).then(response => {
      return response.json();
    }).then(response => {
      console.log(response);
    })
  }

server.js

//fetch服务
app.all('/fetch-server',(request,response) => {
  //设置响应头 设置允许跨域
  response.setHeader('Access-Control-Allow-Origin','*')
  //允许前端自定义响应头
  response.setHeader('Access-Control-Allow-Headers','*')
  const data = {name:'sun'};
  response.send(JSON.stringify(data));  
  // response.send('axios');  
});

同源策略

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

违背同源策略就是跨域

单台服务器性能有上限,所以有跨域行为出现

AJAX默认遵循同源策略

同源

index.html

<!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>
  <h1>s</h1>
  <button>点击获取</button>
</body>
<script>
  const btn = document.querySelector('button')
  btn.onclick = function() {
    const x = new XMLHttpRequest();
    //因为是满足同源策略,所以url可以简写
    x.open('GET','/data');
    //发送
    x.send();
    x.onreadystatechange = function() {
      if(x.readyState === 4) {
        if(x.status >= 200 && x.status < 300) 
          console.log(x.response);
      }
    }

  }
</script>
</html>

server.js

const { response } = require('express');
const express = require('express');

const app = express()

app.get('/home',(request,response) => {
  //响应一个页面
  response.sendFile(__dirname + '/index.html')
});

app.get('/data',(request,response) => {
  response.send('用户数据')
})

app.listen(9000,() => {
  console.log('服务已经启动');
})

JSONP

JSON with Padding,是一个非官方的跨域解决方案,只支持get请求

原理:网页中的一些标签(img,link,iframe,script)天生具有跨域能力,所以JSONP是借助script标签的跨域能力来发送请求的

使用

index.html

<!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>
  <style>
    #result {
      width: 300px;
      height: 100px;
      border: solid 1px purple;
    }
  </style>
</head>
<body>
  <div id="result">
  </div>
  <script>
    //处理数据
    function handle(data) {
    //获取result
      const result = document.querySelector('#result');
      result.innerHTML = data.name;
    }
  </script>
  <!-- <script src="http://127.0.0.1:5500/6.%E8%B7%A8%E5%9F%9F/JSONP/app.js"></script> -->
  <script src="http://127.0.0.1:8000/jsonp-server"></script>
</body>
</html>

server.js

//jsonp服务
app.all('/jsonp-server',(request,response) => {
  const data = {
    name:'sun6',
  };

  let str = JSON.stringify(data)
  response.end(`handle(${str})`)
})

jsonp实践

index.html

<!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>
  <style>
    
  </style>
</head>
<body>
  用户名:<input type="text" id="username">
  <p></p>
</body>
<script>
  //获取input元素
  const input = document.querySelector('#username')
  const p = document.querySelector('p')
  //声明函数
  function handle(data) {
    input.style.border = 'solid 1px red';
    //修改p标签提示文本
    p.innerHTML = data.msg
  }

  //绑定事件
  input.onblur = function() {
    //获取用户输入值
    let username = this.value;
    //向服务端发送请求 检测用户是否存在

    //1.创建script标签
    const script = document.createElement('script')
    //2.设置标签的src
    script.src = 'http://127.0.0.1:8000/check-username'
    //3.将script插入文档中
    document.body.appendChild(script);
    
  }
</script>
</html>

server.js

//用户名检测是否存在
app.all('/check-username',(request,response) => {
  const data = {
    exist:1,
    msg:'用户名已经存在'
  };
  let str = JSON.stringify(data)
  response.end(`handle(${str})`)
})

jquery-jsonp

index.html

  $('button').eq(0).click(function() {
    $.getJSON('http://127.0.0.1:8000/jquery-jsonp?callback=?',function(data) {
      $("#result").html(`
        名称:${data.name}
      `)
    })
  });

server.js

//jquery-jsonp
app.all('/jquery-jsonp',(request,response) => {
  const data = {
    name:'sun',
    msg:'6666'
  };
  let str = JSON.stringify(data)
  //接受callback参数
  let cb = request.query.callback;
  response.end(`${cb}(${str})`)
})

jquery 有个callback要注意

CORS

cors(Cross-Origin Resource Sharing)跨域资源共享,CORS是官方的跨域解决方案,它的特点是不需要在客户端做任何特殊的操作,完全在服务器中进行处理,支持get和post请求,

跨域资源共享标准新增了一组HTPP首部字段,允许服务器声明哪些源站通过浏览器有权访问哪些资源

CORS是怎么工作的

CORS是通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应以后就会对响应放行

CORS的使用

主要是服务器的设置

设置响应头

response.setHeader('Access-Control-Allow-Origin','*')

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值