前后端交互-ajax、axios和跨域

1,561 阅读15分钟

URL地址

URL(Uniform Resource Locator)统一资源定位符

作用:标识互联网上每个资源的唯一存放位置

url的结构.png

表单提交

方式:HTML中的<form>标签,就是用于采集用户输入的信息,并通过<form>标签的提交操作,把采集到的信息提交到服务器端进行处理

  <form action='http://111.222.3.444:9999/get' method="GET">
    <input type="text" name='name'  value="admin"> <br>
    <input type="password" name='pwd' value="123456"> <br>
    <!-- 提交数据 -->
    <input type="submit" value="提交-get">
  </form>

  <form action='http://111.222.3.444:9999/post' method="POST">
    <input type="text" name='name' value="admin"> <br>
    <input type="password" name='pwd' value="123456"> <br>
    <!-- 提交数据 -->
    <input type="submit" value="提交-post">
  </form>

表单的属性

action

  1. 指定表单的提交地址,默认值为当前页面的 URL 地址
  2. 当提交表单后,页面会立即跳转到 action 属性指定的 URL 地址

method

  1. 指定表单的提交方式,默认为get
  2. get/post
  • ​ get:

    • 数据会拼接在 url 地址的后面?name=admin&pwd=123456

    • 地址栏有长度限制,因此 get 方式提交数据大小不会超过 4k

    • GET 用于信息获取

  • post:

    • 数据不会在 url 中显示,相比 get 方式,post 更安全

    • 提交的数据没有大小限制

    • POST 表示可能修改服务器上的资源的请求

form表单的注意点

  1. input 的数据想要提交到后台,必须指定name属性,后端通过name属性获取值
  2. 想要提交表单,不能使用 input:button 必须使用 input:submit

HTTP协议

HTTP协议(Hypertext transfer protocol)超文本传输协议

作用:HTTP协议规定了客户端与服务器之间进行的网页内容传输时, 所必须遵守的传输格式

get 请求的请求报文详解

//--------------------------请求行--------------------------------
GET /day02/01.php?username=lw&password=123456 HTTP/1.1
// GET  请求方式
// /day02/01.php?username=lw&password=123456    请求路径+参数(注意点)
// HTTP/1.1 HTTP的版本号

//--------------------------请求头--------------------------------
// Host:主机地址
Host: www.study.com
// HTTP1.1版本默认开启,建立过连接后,TCP连接不会断开,下次连接可以继续使用
Connection: keep-alive
//chrome浏览器自己增加的
Upgrade-Insecure-Requests: 1
//浏览器的代理字符串(版本信息)
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
//浏览器端可以接受的类型。
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,`*/*`;q=0.8
//从哪个页面发出的请求
Referer: http://www.study.com/day02/01-login.html
//检查浏览器支持的压缩方式
Accept-Encoding: gzip, deflate, sdch
//浏览器支持的语言,优先中文。
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

//----------------------------请求体-------------------------------------
// get请求没有请求体,但是参数会拼接到请求行中

POST 请求的请求报文

//-----------------------请求行---------------------------------------------
POST /day02/01.php HTTP/1.1

//-----------------------请求头--------------------------------------------
Host: www.study.com
Connection: keep-alive
// ★ 传递的参数的长度。
Content-Length: 29
Cache-Control: max-age=0
Origin: http://www.study.com
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.96 Safari/537.36
// ★ 内容类型:表单数据,如果是post请求,必须指定这个属性。
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,`*/*`;q=0.8
Referer: http://www.study.com/day02/01-login.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

//------------------------请求体------------------------------------------
username=lw&password=123456

GET 请求与 POST 请求的对比

  • GET 请求没有请求体,因为 GET 请求的参数拼接到地址栏中了
  • POST 请求有请求体,就是传递的参数
  • POST 请求需要指定 content-type 属性。

响应与响应报文

//---------------------状态行(响应行)-------------------------------
HTTP/1.1 200 OK
//HTTP/1.1  HTTP版本
//200 响应的状态
	//200表示成功
	//404表示找不到资源
	//500表示服务端错误


//----------------------响应头-----------------------------------------------
Date: Thu, 22 Jun 2017 16:51:22 GMT
Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2j PHP/5.4.45
X-Powered-By: PHP/5.4.45
Content-Length: 18
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
//内容类型,告诉浏览器该如何解析响应结果
Content-Type: text/html;charset=utf-8

//-----------------------响应体------------------------------------------------
用户登录成功

可以直接使用谷歌浏览器来查看请求报文和响应报文。谷歌浏览器会对报文进行一定的格式化,看起来虽然不是原生的报文,但是使用起来更加的方便简洁。

Ajax

ajax(Asynchronous Javascript And XML)异步JavaScript和XML

作用:在 HTTP 协议的基础上以异步的方式与服务器进行通信

传统的Ajax与JQuery ajax

传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱 (在异步js里,回调函数写的太多,回调套回调,代码繁琐)

JQuery ajax 是对原生XHR的封装,除此以外还增添了对JSONP的支持

ajax和form表单的对比

  1. 都能够发送http请求,ajax发送的是异步的http请求,表单发送的是同步的http请求
  2. 使用表单发送请求,页面一定会发生跳转;ajax允许你在操作页面的同时异步的发送请求,页面可以不跳转

传统的Ajax(XMLHttpRequest)

XMLHttpRequest(简称 xhr)是浏览器提供的 Javascript 对象,用于与服务器通信(交换数据)。

作用:实现对网页的部分更新,而不是刷新整个页面。这个请求是异步,即在往服务器发送请求时,并不会阻碍程序的运行,浏览器会继续渲染后续的结构。

最简单的用法 let xhr = new XMLHttpRequest()

发送 get 请求

使用XMLHttpRequest发送get请求的步骤:

  1. 创建 xhr 对象

    let xhr = new XMLHttpRequest()

  2. 请求行 - 调用 xhr.open() 函数

    xhr.open( ‘ get ’ , ' url地址 ?参数拼接的字符串 ' )

  3. 请求体 - 调用 xhr.send() 函数

    xhr.send(null)

// 点击按钮准备 
<button>发送请求 </button>
let btn =  document.querySelector('button')
btn.onclick =  function () { ... }

//1. 创建一个ajax对象, xhr 就是ajax实例, 可以发送请求 
var xhr = new XMLHttpRequest(); 

// 2. 设置请求的三部分
// 2.1 设置请求行
// 参数1 :请求方式
// 参数2 : 请求url地址 
xhr.open('get', 'http://111.222.3.444:9999/v1/get?name=admin&pwd=123456')

// 2.2 需要设置请求头 
// get请求的请求头浏览器默认会添加, 此处不用设置请起头了

// 2.3 设置请求体  get请求没有请求体, 因为请求体就是放参数的, 参数已经拼在 url上了
// 注意:必须调用send才会发送请求,get请求,参数为null
// 参数:请求体
xhr.send()

发送 post 请求

步骤:

  1. 创建 xhr 对象

    let xhr = new XMLHttpRequest()

  2. 请求行 - 调用 xhr.open() 函数

    xhr.open( ‘ post ’ , ' url地址 ' )

  3. 请求头 - 设置 Content-Type 属性(固定写法)

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

  4. 请求体 - 调用 xhr.send() 函数,同时指定要发送的数据

    xhr.send( 参数拼接的字符串 )

 // 1. 创建 xhr 
let xhr = new XMLHttpRequest()

// 2. 请求
// 2.1 请求行
xhr.open('post','http://111.222.3.444:9999/v1/post')

// 2.2 请求头
// Content-Type: application/x-www-form-urlencoded
xhr.setRequestHeader('content-type','application/x-www-form-urlencoded')

// 2.3 请求体
xhr.send('name=admin&pwd=123456')
  • post 请求, 参数列表不能拼接到 url 后面
  • post 必须设置请求头中的 content-type 为 application/x-www-form-urlencoded
  • post 请求需要将参数放到send中

获取响应

// 结构  
  <input type="text" class="name" placeholder="账号"> <br>
  <input type="text" class="pwd" placeholder="密码"> <br>
  <button>提交</button>
// 点击按钮准备 
let btn =  document.querySelector('button')
btn.onclick =  function () { ... }

      // 1. 收集数据
      let name = document.querySelector('.name').value
      let pwd = document.querySelector('.pwd').value

      // 2. 发送ajax 请求
      let xhr = new XMLHttpRequest()

      xhr.open('get', `http://111.222.3.444:9999/v1/get?name=${name}&pwd=${pwd}`)
      xhr.send()

      // 3. 获取响应
      xhr.onload = function () {
        // console.log(xhr);
        // console.log(xhr.status);
        // console.log(xhr.responseText);

        if (xhr.status === 200) {
          alert(xhr.responseText)
        } else {
          alert('请求失败')
         }
      }

jQuery 中的 ajax 方法

jQuery 中发起 Ajax 请求最常用的三个方法如下:

jq中的Ajax.png

$.ajax的参数列表

参数名称描述取值示例
url后台地址url:"02.php"
type请求方式get/posttype:"get"
dataType服务器返回的数据格式json/xml/text,如果不指定,会自动根据 content-type 进行判定dataType:"json"
data发送的请求数据对象、字符串data:{name:"zs", age:18}
beforeSend调用前的回调函数,在 beforeSend 中 return false,会阻止 ajax 的发送function(){}beforeSend:function(){ }
success成功的回调函数function (data) {}success:function (data) {}
error失败的回调函数function (error) {}error:function(data) {}
complete完成后的回调函数function () {}complete:function () {}

示例:

$.ajax({
    type: "get", //请求类型
    url: "02.php", //请求地址
    data: { name: "zs", age: 18 }, //请求数据
    beforeSend: function() {
        //alert("发送ajax前调用");
    },
    success: function(data) {
        //alert("请求成功时调用");
        console.log(data);
    },
    error: function(error) {
        //alert("请求失败时调用");
        console.log(error);
    },
    complete: function() {
        //alert("请求完成时调用, 不论失败还是成功都会执行");
    },
});

$.ajax() 函数的基本语法:

$.ajax({
   type: '', // 请求的方式,例如 GET 或 POST
   url: '',  // 请求的 URL 地址
   data: { },// 这次请求要携带的数据
   success: function(res) { } // 请求成功之后的回调函数
})

通过JQuery ajax提交表单数据(★)

步骤:

  1. 监听表单提交事件

  2. 阻止表单默认提交行为

    event.preventDefault() ,阻止表单的提交和页面的跳转

  3. 快速获取表单中的数据(表单序列化,JQ的方法)

    $('form').serialize()函数 或者 $('form').serializeArray()

    作用:

    • 将表单中带有 name 属性的所有参数拼成一个格式为name=value&name1=value1这样的查询字符串格式。方便我们获取表单的数据;

    • jquery 的 ajax 方法的data 参数能够直接识别表单序列化的数据

  4. 清空全部(JQ的方法)

    $('form')[0].reset()

  <!-- 
    1. 收集数据 
    2. 发送请求
   -->
  <form action="http://111.222.3.444:9999/v1/get">
    <input type="text" name='bookname'  placeholder="书名"> <br>
    <input type="text" name='author' placeholder="作者"> <br>
    <input type="text" name='publisher' placeholder="出版社"> <br>
    <input type="submit" class="submit" value="提交">
  </form>

  <script src="./jquery.js"></script>
  <script>

    $('input[type=submit]').on('click', (e)=>{
      
      //1. 替换 : 发送请求
      //1. 阻止默认行为
      e.preventDefault()
      console.log('这里要发送请求了- $.ajax');

      //2. 替换 : 获取数据

      // 替换方式1 : 
      // let v1 = $('input[name=bookname]').val()
      // let v2 = $('input[name=author]').val()
      // let v3 = $('input[name=publisher]').val()
      // console.log(v1,v2,v3);
      // console.log(`bookname=${v1}&author=${v2}&publisher=${v3}`);

      // 方式2 : 
      let res =  $('form').serialize()
      console.log(res);

      //3. 清空
       $('form')[0].reset()
    })

  </script>

XMLHttpRequest Level2的新特性

设置 HTTP 请求的时限

  • xhr版本
//1. 调试 network 里面的 Slow 3G,人为降低网速

//2. 调试接口

xhr.timeout = 1000; // 单位是ms
// 上面的语句,将最长等待时间设为 1000 毫秒。过了这个时限,就自动停止HTTP请求。

// 与之配套的还有一个 timeout 事件,用来指定回调函数:
xhr.ontimeout = function(event){
    alert('请求超时!')
}
  • jquery版本
   $.ajax({
        url: 'http://111.222.3.444:9999/api/getbooks',
       // 设置超时时间
        timeout:1000,
        success: function (res) {
          console.log('res:', res);
        },
        error:function(err){
          console.log('err:',err);// 超时
        }
      })

通过FormData对象传输文件(★)

为了方便表单处理,HTML5 新增了一个 FormData 对象

作用有两个 ;

  1. 收集整个表单的数据 类似于 $('form').serialize() (FormData 原生JS和JQ都能使用)

  2. 上传文件

FormData对象管理表单数据

  <form>
    <input type="text" name="name"> <br>
    <input type="text" name="pwd"> <br>
    <button>按钮</button>
  </form>

    // 收集数据
    //1. 拿到input, 再获取value
    //2. serizlize()  $('form').serialize()
    //3. 使用 formdata 

      //1. 创建一个空的formdata
      let fd = new FormData()  // 这个是创建一个空的fd
      fd.append('username','马哥')
      fd.append('age',90)
     
      fd.forEach((v,k) => {
        console.log(v,k);
      })
  
      //2. 创建一个formdata, 放一个表单,这样的话,就直接把表单数据获取了
      let fd = new FormData(document.querySelector('form'))
      fd.forEach((v,k) => {
        console.log(v,k);
      })

测试上传 fd 数据

 <form>
    <input type="text" name="name"> <br>
    <input type="text" name="age">   <br>
    <button>按钮</button>
  </form>

// 创建 fd 并收集数据
let fd = new FormData(document.querySelector('form'))

let xhr = new XMLHttpRequest()
// 虽然这个接口特殊,但是能说明这样确实可以上传的
// 不需要设置请求头
xhr.open('post','http://111.222.3.444:9999/api/formdata')
xhr.send(fd)

xhr.onload = function () {
    console.log(xhr.responseText);
}

原生XHR上传文件-form+name

新版 XMLHttpRequest 对象,不仅可以发送文本信息,还可以上传文件。

<!-- 文件选择框 -->
<form>
    <input type="file" name='avatar' />
</form>
  <style>
    div {
      width: 400px;
      height: 400px;
      border: 1px solid #000;
    }

    img {
      width: 100%;
      height: 100%;
    }

  </style>

 <script>
      // 需求:使用ajax上传图片
      const input = document.querySelector('input')
      const form = document.querySelector('form')
      const div = document.querySelector('div')
      // 让选择的文件发生了改变
      input.onchange = function () {
        console.log('哈哈哈')
        // 发送ajax请求,上传图片
        const xhr = new XMLHttpRequest()

        xhr.open('post', 'http://111.222.3.444:9999/api/upload/avatar')
        // 不能设置请求头
        const fd = new FormData(form)

        xhr.send(fd)

        xhr.onload = function () {
          console.log(xhr.responseText)
          const res = JSON.parse(xhr.responseText)
          div.innerHTML = `<img src="http://111.222.3.444:9999${res.url}">`
        }
      }
    </script>

原生XHR上传文件-input + append

// 收集图片数据 name='avatar'
let fd = new FormData()
fd.append('avatar',this.files[0])
xhr.send(fd)

使用jQuery上传文件

<script>
  $('input').on('change', function () {
    const fd = new FormData()
    fd.append('avatar', this.files[0])
   
    $.ajax({
      type: 'post',
      url: 'http://www.111.222.3.444:9999/api/upload/avatar',
      data: fd,
      // 不修改 Content-Type 属性,使用 FormData 默认的 Content-Type 值
      contentType: false,
      // 不对 FormData 中的数据进行 url 编码,而是将 FormData 数据原样发送到服务器
      processData: false,
      success(res) {
        console.log(res)
        $('div').html(
          `<img src="http://111.222.3.444:9999${res.url}">`
        )
      },
      // 用于增强xhr,必须返回一个xhr对象
      xhr() {
        const xhr = new XMLHttpRequest()
        xhr.upload.onprogress = function (e) {
          $('progress').attr('max', e.total)
          $('progress').attr('value', e.loaded)
        }
        return xhr
      },
    })
  })
</script>

文件上传进度条

<!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>
        div {
            width: 300px;
            height: 300px;
            border: 1px solid #000;
        }
        img {
            width: 100%;
        }
    </style>
</head>
<body>
    <form>
        <input type="file" name="avatar">
        <div></div>
    </form>
    
    <!-- HTML中的<progress>元素用来显示一项任务的完成进度 -->
    <progress value="" max="" hidden></progress>
	<!-- max描述进度条的总工作量 -->
    <!-- value描述进度条已完成的工作量 -->
    <script>
        let ipt=document.querySelector('input[type=file]')
        let div=document.querySelector('div')
        let progress=document.querySelector('progress')

        ipt.onchange= function () {
            progress.hidden=false

            let fd=new FormData(document.querySelector('form'))
            let xhr=new XMLHttpRequest()
            xhr.open('post','http://111.222.3.444:9999/api/upload/avatar')

            // 监听上传
            xhr.upload.onprogress= function (e) {
				// event.loaded  已传输的数据量
				// event.total  总共的数据量
                console.log(e.loaded,e.total);
                progress.max=e.total
                progress.value=e.loaded
            }
            xhr.upload.onload= function () {
                progress.hidden=true
            }

            xhr.send(fd)
            xhr.onload= function () {
                console.log(xhr.responseText);
                let res=JSON.parse(xhr.responseText)
                div.innerHTML=`<img src="http://111.222.3.444:9999${res.url}">`
            }
            
        }
    </script>
</body>
</html>

Axios(★★★)

axios中文文档 www.axios-js.com/zh-cn/docs/

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范。

特征:

  1. 从浏览器中创建 XMLHttpRequests
  2. 从 node.js 创建 http 请求
  3. 支持 Promise API
  4. 拦截请求和响应
  5. 转换请求数据和响应数据
  6. 取消请求
  7. 自动转换 JSON 数据
  8. 客户端支持防御 XSRF

请求配置

这些是创建请求时可以用的配置选项。只有 url 是必需的。如果没有指定 method,请求将默认使用 get 方法

{
   // (★)`url` 是用于请求的服务器 URL
  url: '/user',

  // (★)`method` 是创建请求时使用的方法
  method: 'get', // default

  // (★)`baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
  // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
  baseURL: 'https://some-domain.com/api/',

  // `transformRequest` 允许在向服务器发送前,修改请求数据
  // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  transformRequest: [function (data, headers) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
  transformResponse: [function (data) {
    // 对 data 进行任意转换处理
    return data;
  }],

  // (★)`headers` 是即将被发送的自定义请求头
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // (★)`params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params: {
    ID: 12345
  },

   // `paramsSerializer` 是一个负责 `params` 序列化的函数
  // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  paramsSerializer: function(params) {
    return Qs.stringify(params, {arrayFormat: 'brackets'})
  },

  // (★★)`data` 是作为请求主体被发送的数据
  // 只适用于这些请求方法 'PUT', 'POST', 和 'PATCH'
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data: {
    firstName: 'Fred'
  },

  // (★)`timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout: 1000,

   // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials: false, // default

  // `adapter` 允许自定义处理请求,以使测试更轻松
  // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  adapter: function (config) {
    /* ... */
  },

 // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth: {
    username: 'janedoe',
    password: 's00pers3cret'
  },

   // (★)`responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // default

  // `responseEncoding` indicates encoding to use for decoding responses
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  responseEncoding: 'utf8', // default

   // `xsrfCookieName` 是用作 xsrf token 的值的cookie的名称
  xsrfCookieName: 'XSRF-TOKEN', // default

  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
  xsrfHeaderName: 'X-XSRF-TOKEN', // default

   // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress: function (progressEvent) {
    // Do whatever you want with the native progress event
  },

  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress: function (progressEvent) {
    // 对原生进度事件的处理
  },

   // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength: 2000,

  // `validateStatus` 定义对于给定的HTTP 响应状态码是 resolve 或 reject  promise 。如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),promise 将被 resolve; 否则,promise 将被 rejecte
  validateStatus: function (status) {
    return status >= 200 && status < 300; // default
  },

  // `maxRedirects` 定义在 node.js 中 follow 的最大重定向数目
  // 如果设置为0,将不会 follow 任何重定向
  maxRedirects: 5, // default

  // `socketPath` defines a UNIX Socket to be used in node.js.
  // e.g. '/var/run/docker.sock' to send requests to the docker daemon.
  // Only either `socketPath` or `proxy` can be specified.
  // If both are specified, `socketPath` is used.
  socketPath: null, // default

  // `httpAgent` 和 `httpsAgent` 分别在 node.js 中用于定义在执行 http 和 https 时使用的自定义代理。允许像这样配置选项:
  // `keepAlive` 默认没有启用
  httpAgent: new http.Agent({ keepAlive: true }),
  httpsAgent: new https.Agent({ keepAlive: true }),

  // 'proxy' 定义代理服务器的主机名称和端口
  // `auth` 表示 HTTP 基础验证应当用于连接代理,并提供凭据
  // 这将会设置一个 `Proxy-Authorization` 头,覆写掉已有的通过使用 `header` 设置的自定义 `Proxy-Authorization` 头。
  proxy: {
    host: '127.0.0.1',
    port: 9000,
    auth: {
      username: 'mikeymike',
      password: 'rapunz3l'
    }
  },

  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken: new CancelToken(function (cancel) {
  })
}

axios发起GET请求

axios.get(url,{
    headers: {}, //headers携带自定义的请求头,如token
    params : {}	// axios.get一般将需要携带的参数拼接在url后面,也可以使用params
})
或者
axios.get(url?字符串,{
    headers: {}
})

代码演示

// axios.get(url,config)
// 方式一:拼接在url后面,以字符串形式
axios.get('http://111.222.3.444:9999/v1/get?name=admin&pwd=123456'
// 方式二:使用params,以键值对形式
axios.get('http://111.222.3.444:9999/v1/get', {
    params: {
        name: 'admin',
        pwd: 123456
    }
}).then(res => {
    console.log('res', res);
})

axios发起POST请求

axios.post( url , data , {
    headers: {}	//headers携带自定义的请求头,如token
})
// data为axios.get携带的参数(范围极为广泛,见上面),在请求前收集好
// params:{}在axios.post形式极为罕见,不使用

代码演示

// 发表评论接口
// 第一种 : 参数是字符串
axios.post('http://111.222.3.444:9999/api/addcmt', 'username=aaaa&content=123').then(res => {
  console.log('res', res);
})
// 第二种 : 参数是对象
axios.post('http://111.222.3.444:9999/api/addcmt', { username: 'admin', content: 123456 }).then(res => {
  console.log('res', res);
})

直接使用axios发起请求 (不建议使用)

axios({
    method: '请求类型',
    url: '请求的URL地址',
    data: { /* POST数据 */ },
    params: { /* GET参数 */ }
}) .then(callback)

响应结构

某个请求的响应包含以下信息

{
  // `data` 由服务器提供的响应
  data: {},

  // `status` 来自服务器响应的 HTTP 状态码
  status: 200,

  // `statusText` 来自服务器响应的 HTTP 状态信息
  statusText: 'OK',

  // `headers` 服务器响应的头
  headers: {},

   // `config` 是为请求提供的配置信息
  config: {},
 // 'request'
  // `request` is the request that generated this response
  // It is the last ClientRequest instance in node.js (in redirects)
  // and an XMLHttpRequest instance the browser
  request: {}
}

使用 then 时,响应如下 :

axios.get('/user/12345')
  .then(function(response) {
    console.log(response.data);
    console.log(response.data);
    console.log(response.status);
    console.log(response.statusText);
    console.log(response.headers);
    console.log(response.config);
  })
简写为:
axios.get('/user/12345')
  .then(res => {
    console.log(res);
    // res对象中的数据按需使用就行
  })

全局的 axios 默认值

// 默认的baseURL,配置后请求中的url可省略baseURL不写
axios.defaults.baseURL = 'https://api.example.com';
// 默认的headers,配置后请求中的headers可不写(由于有些请求没有header,一般使用条件语句来有选择的配置)
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
// 默认的Content-Type,很少用
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';

拦截器

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  });

同源和跨域

同源策略

同源的定义

同源的网站,有三个相同:协议域名端口

举例来说,http://www.test.com/index.html 这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。

http协议默认端口80,https默认端口443

http://www.test.com/other.html  	同源(协议、域名、端口相同)
https://www.test.com/about.html		协议不同(http 与 https)
http://blog.test.com/movie.html		域名不同(www.test.com 与 blog.test.com)
http://www.test.com:7001/home.html	端口不同(默认的 80 端口与 7001 端口)
http://www.test.com:80/main.html	同源(协议、域名、端口相同)

同源的目的

保证用户信息的安全,防止恶意的网站窃取数据

跨域

违反浏览器的同源策略就是跨域

跨域时浏览器的报文

  • 允许跨域前

console控制台报错信息:

跨域.png

network情况:

允许跨域前1.png

允许跨域前2.png

  • 允许跨域后

console控制台无报错

network情况正常:

允许跨域后.png

允许跨域后2.png

解决跨域的方法(需要从后端入手)

JSONP(较少使用)

前提:script 标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源。类似的还有imglink标签

<!--不受同源策略的标签-->
<img src="http://www.api.com/1.jpg" alt="" />
<link rel="stylesheet" href="http://www.api.com/1.css" />
<script src="http://www.api.com/1.js"></script>

原理:借助了script标签不受同源策略的限制,在服务端返回一个函数的调用,将数据作为当前调用函数的实参。 在浏览器端,需要程序要声明一个函数,通过形参就可以获取到服务端返回的对应的值。

注意点:JSONP只在get请求下有用

  <script>
    function success(res) {
      console.log(res);
    }
  </script>
  <script src="http://111.229.6.231:9996/v1/jsonp2?callback=success"></script>

CORS(较常见)

CORS(Cross-Origin Resource Sharing)跨源资源共享

CORS 的具体流程(★)
  1. 浏览器会向发送一条请求,服务器接受到请求之后,会返回请求头信息,浏览器查看返回的响应头信息中是否设置了header('Access-Control-Allow-Origin:请求源域名或者*');
  2. 如果没有设置,说明服务器不允许使用 cors 跨域,那么浏览器会把获取到的数据拦截。
  3. 如果返回的响应头中设置了header('Access-Control-Allow-Origin:请求源域名或者*');,浏览器会跟请求头中的Origin: http://www.study.com进行对比,如果满足要求,就把数据发送给用户。
  4. 结论:跨域行为是浏览器行为,是浏览器阻止了 ajax 行为。服务器与服务器之间是不存在跨域的问题的
  5. 注意:浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到!

详细见官方中文文档developer.mozilla.org/zh-CN/docs/…

跨域本质.png

jsonp 与 cors 的对比
  • jsonp 兼容性好,老版本浏览器也支持

  • 缺点是只支持 GET 请求,不支持 POST 请求。

  • 发送的数据量有限。使用麻烦

  • CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。

    • 支持 GET 和 POST 请求。
    • 缺点是不兼容某些低版本的浏览器。(浏览器支持 cors 功能才行)
    • 但是使用简单,只要服务端设置允许跨域,对于客户端来说,跟普通的 get、post 请求并没有什么区别。
  • 跨域的安全性问题:跨域并不会带来安全性问题,因为跨域是需要服务端配合的 ,也就是说不论 jsonp 还是 cors,如果没有服务端的允许,浏览器是没法做到跨域的。

node中(后端)设置允许跨域:

方式一:

node设置允许跨域1.png

方式二:

node设置允许跨域2.png

反向代理

原理:服务器与服务器之间是不存在跨域的问题

如Nginx就是性能非常好的反向代理服务器,用来做负载均衡。

正向代理

正向代理.jpg

反向代理

反向代理.jpg

​ 反向代理的实现: ​ ①需要有一个负载均衡设备来分发用户请求,将用户请求分发到空闲的服务器上

​ ②服务器返回自己的服务到负载均衡设备

​ ③负载均衡将服务器的服务返回用户

正向代理和反向代理的区别:正向代理隐藏真实客户端,反向代理隐藏真实服务端