ajax

140 阅读7分钟

一、ajax工作流程

  1. get

        //get
        //(1).实例化ajax对象
        let xhr = new XMLHttpRequest()
        //(2).设置请求方法和地址
        //get请求的数据直接添加在url的后面 格式是 url?key=value
        xhr.open('get', '接口url')
        //(3).发送请求
        xhr.send()
        //(4).注册回调函数
        xhr.onload = function () {
          console.log(xhr.responseText)
        }
    
  2. post

        //post
        //(1).实例化ajax对象
        let xhr = new XMLHttpRequest()
        //(2).设置请求方法和地址
        xhr.open('post', '')
        //(3).设置请求头(post请求才需要设置)
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded')
        //(4).发送请求 : 参数格式  'key=value' 
        xhr.send('key=value')
        //(5).注册回调函数
        xhr.onload = function () {
          console.log(xhr.responseText)
        }
    

二、axios框架

axios基本语法

  <body>
    <button class="btn1">基本使用</button>
    <button class="btn2">点我发送get请求</button>
    <button class="btn3">点我发送post请求</button>

    <!-- 导入axios -->
    <script src="./axios.js"></script>

    <script>
      /* 
      axios语法 :
        axios
         .get('url')
         .then( res=>{ //请求成功 } )
         .catch( err=>{ //请求错误} )
         .then( ()=>{ //请求完成 } )
      */

      //基本使用
      document.querySelector(".btn1").onclick = function() {
        axios
        .get('https://autumnfish.cn/api/joke/list?num=10')
        .then(res=>{
          // res : 是axios库对响应数据做了一层包装
          console.log(res)
          // res.data : 才是服务器响应的数据, axios库自动把json转js
          console.log( res.data )
        })
        .catch(err=>{
          //网络错误 :  (1)url路径写错了   (2)网络错误
          console.log(err)
        }).then( ()=>{
          //本次请求完成,无论成功失败
          console.log( '本次请求完成' )
        } )
      }
      //点我发送get请求
      document.querySelector(".btn2").onclick = function() {
        axios.get('https://autumnfish.cn/api/joke/list',{
          params:{ num:10 }
        })
        .then(res=>{ 
          console.log(res)
        })
      }

      //点我发送post请求
      document.querySelector(".btn3").onclick = function() {
        axios.post('http://www.liulongbin.top:3009/api/login',{
          username:'sfs',
          password:'adada'
        }).then(res=>{
          console.log( res )
        })
      }
    </script>

axios推荐使用方式

  <body>
    <button class="btn1">基本使用</button>
    <button class="btn2">点我发送get请求</button>
    <button class="btn3">点我发送post请求</button>

    <!-- 导入axios -->
    <script src="./axios.js"></script>

    <script>
      /* 
      axios语法 :
        axios
         .get('url')
         .then( res=>{ //请求成功 } )
         .catch( err=>{ //请求错误} )
         .then( ()=>{ //请求完成 } )

      axios常用语法 :
        axios({
          method:'请求方法',
          url:'请求路径',
          params : { get参数 },
          data : { post参数 }
        }).then( res=>{} )
      */
      
      //基本使用
      document.querySelector(".btn1").onclick = function() {
        axios({
          method:'get',
          url:'https://autumnfish.cn/api/joke/list?num=10'
        }).then(res=>{
          console.log( res )
        })
      }
      //点我发送get请求
      document.querySelector(".btn2").onclick = function() {
        axios({
          method:'get',
          url:'https://autumnfish.cn/api/joke/list',
          params:{ num:10 }
        }).then(res=>{
          console.log(res)
        })
      }

      //点我发送post请求
      document.querySelector(".btn3").onclick = function() {
        axios({
          method:'post',
          url:'http://www.liulongbin.top:3009/api/login',
          data:{ username:'admin',password:'123456' }
        }).then(res=>{
          console.log(res)
        })
      }
    </script>

ajax工作原理

      /* 
      1. http协议 :  网络传输协议
        * 协议 : 规定网络数据传输格式
        
      2. http协议组成 :  请求报文 + 响应报文
        * 浏览器发请求 必须是 : 请求报文 
        * 服务器响应 必须是 :   响应报文 

      3. 请求报文 由三部分组成
        3.1 请求行 :  请求方法 + 请求地址
        3.2 请求头 :  浏览器告诉服务器,我发送给你的数据是什么格式 (文本、json、图片、音视频等等)
        3.3 请求体 :  请求参数

      4. 响应报文 由三部分组成
        4.1 响应行 :  服务器状态码、 服务器地址等
          2xx : 请求成功   200:成功  
          3xx : 重定向 302 服务端重定向(服务器主动修改浏览器网址)
          4xx : 前端的问题   404 : url错误    400: 参数错误   403/402 : 没有权限  405:请求方法错误
          5xx : 服务器的问题  500 服务器挂了(后台java代码像js一样爆红了)
        4.2 响应头 :  服务器告诉浏览器,我响应给你的数据是什么格式 (文本、json、图片、音视频等等)
        4.3 响应体 :  服务器响应数据
      
      5.ajax原理 : 发送请求报文过程
        * 给服务器发请求,其实发的就是请求报文
      */

      //(1).实例化ajax对象
      let xhr = new XMLHttpRequest()
      //请求未初始化
      console.log(xhr.readyState) //0

      //(2).设置请求方法和地址(请求行)
      xhr.open("post", "http://www.liulongbin.top:3009/api/login")
      //服务器连接已建立
      console.log(xhr.readyState) //1

      //(3).设置请求头(post请求才需要设置)
      xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
      //(4).发送请求 : 参数格式  'key=value'
      xhr.send("username=admin&password=123456")
      
      //(5).注册回调函数
      xhr.onreadystatechange = function() {
        console.log(xhr.readyState) //2 3 4

        //当readyState为4,表示响应数据了
        if (xhr.readyState == 4) {
          console.log(xhr.response)
        }
      }

原理.png

网页从输入url到呈现页面过程

        /* 网页从输入url到呈现过程
        1.DNS解析 :  把域名解析成ip地址
        2.TCP连接三次握手 :  建立 安全可靠的传输协议
            2.1 什么是TCP : 一种 传输控制协议
            2.2 TCP作用 :  保证HTTP网络传输是 安全 + 可靠的 (检测客户端 与 服务器的网卡是不是通的)
            2.3 TCP三次握手 : 
                第一次:  浏览器  -> 服务器   (你能听到我说话吗?,检测浏览器:发送)
                第二次:  服务器  -> 浏览器   (我听到了,你能听到我说话吗。 检测浏服务器: 接收 + 发送)
                第三次:  浏览器 -> 服务器    (嗯,我听到了. 检测浏览器: 接收)
        3.HTTP请求 : 网络传输协议
            3.1 浏览器发送请求 
            3.2 服务器处理请求
            3.3 服务器响应请求
        4.服务器响应数据之后,渲染引擎开始渲染页面
            4.1 解析html生成:dom树
            4.2 解析css生成:样式树
            4.3 dom树 与 样式树 合并得到 渲染树
            4.4 呈现页面
        */

tcp.png

js链式语法

        /* 
        1.链式语法 : 对象可以连续调用方法
            axios.get().then().catch()
        2.链式语法底层原理 : 在对象的方法中返回自身
        */

        let obj = {
            name: '张三',
            age: 20,
            sex: '男'
        }

        //给对象添加方法
        obj.setName = function (str) {
            this.name = str
            return this
        }

        obj.setAge = function (num) {
            this.age = num
            return this
        }

        obj.setSex = function (str) {
            this.sex = str
            return this
        }

        //调用方法
        obj
            .setName('李四')
            .setAge(22)
            .setSex('女')

        console.log(obj)//{name: '李四', age: 22, sex: '女', setName: ƒ, setAge: ƒ, …}

onreadystatechange事件

        /* 学习目标: XMLHttpRequest对象的两个事件 +  xhr对象的请求状态
        1. onload事件 :  服务器响应之后执行 ( 一次请求,只会执行一次 )
        2. onreadystatechange事件 : xhr请求状态变化会执行 ( 一次请求,会执行多次 )
          0: 请求未初始化  (open之前)
          1: 服务器连接已建立 (open之后)
          2: 请求已接收 ( 服务器已经收到你的请求 )
          3: 请求处理中 ( 服务器正在处理你的请求 )
          4: 请求已完成,且响应已就绪 ( 服务器完成响应, onload事件就是在这里执行 )
        */

        //(1).实例化ajax对象
        let xhr = new XMLHttpRequest()
        //请求未初始化
        console.log( xhr.readyState )//0
      
        //(2).设置请求方法和地址(请求行)
        xhr.open('post', 'http://www.liulongbin.top:3009/api/login')
        //服务器连接已建立
        console.log( xhr.readyState )//1

        //(3).设置请求头(post请求才需要设置)
        xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
        //(4).发送请求 : 参数格式  'key=value' 
        xhr.send('username=admin&password=123456') 
        //(5).注册回调函数
        xhr.onreadystatechange = function () {
          console.log( xhr.readyState )//2 3 4
          
          //当readyState为4,表示响应数据了
          if( xhr.readyState == 4 ){
            console.log( xhr.response )
          }
        }

ajax组成部分

        /* 
        Ajax(阿贾克斯) : Asynchronous Javascript And XML (异步js与XML)
          * 说人话 : 用js发送异步请求
          
        A : Asynchronous 异步
          同步: 按照顺序从上往下依次执行
          异步: 不会立即执行,而是过一会儿执行
            * ECMAScript只有两个语法是异步 :  定时器 + ajax
            * 事件也是异步的,只是事件属于dom语法。 一般讨论同步异步不包含事件。  
        J : Javascript
        A : And
        X : XML (与json完全一致,也是解决数据跨平台传输)  与  XMLHttpRequest
          * ajax技术诞生的时候,json还没有流行。 那个时候主要使用 XML数据格式 , 但是随着json问             世,xml逐渐被json所取代。但是这个ajax的x代表xml称呼一直保留至今。    
        */

        //(1).实例化ajax对象
        let xhr = new XMLHttpRequest()
        //(2).设置请求方法和地址
        //get请求的数据直接添加在url的后面 格式是 url?key=value
        xhr.open('get', 'http://wthrcdn.etouch.cn/WeatherApi?city=武汉')
        //(3).发送请求
        xhr.send()
        //(4).注册回调函数
        xhr.onload = function() {
          console.log(xhr.responseText)
        }

get和post的区别

  1. 传参方式不同

    get参数在url后面拼接(请求行)

    post参数在请求体中发送

  2. 数据大小不同

    get有大小限制,一般 2-5MB

    post没有大小限制(文件上传)

  3. 传输速度不同

    get传输速度快

    post传输速度慢

  4. 安全性不同

    get安全性低

    post安全性高(登录、注册必须是post请求)

头像上传

    <style>
      .thumb-box {
        text-align: center;
        margin-top: 50px;
      }

      .thumb {
        width: 250px;
        height: 250px;
        object-fit: cover;
        border-radius: 50%;
      }
    </style>
  </head>

  <body>
    <div class="thumb-box">
      <!-- 头像 -->
      <img src="./images/cover.jpg" class="img-thumbnail thumb" alt="" />
      <div class="mt-2">
        <!-- 文件选择框 -->
        <!-- accept 属性表示可选择的文件类型 -->
        <!-- image/* 表示只允许选择图片类型的文件 -->
        <input type="file" id="iptFile" accept="image/*" />
        <br />
      </div>
    </div>

    >
    <script src="./lib/axios.js"></script>

    <script>
      /*文件上传 
      1.前置知识点
        1.1 file表单, 默认自带点击事件,作用是选择文件
        1.2 上传文件‘必须’要使用原生内置的FormData对象
          (1)文件需要设置单独的请求头 : multipart/form-data
          (2)文件以二进制方式传输(文本是utf8编码,但是文件不是)
        1.3 file表单有一个特殊的事件onchange事件 : 用户选择了文件就会执行

      2.文件上传流程
        2.1 在file表单的onchange事件中获取用户选择的图片
           this.files[0]
        2.2 创建FormData对象,将图片添加到fd对象中
          let fd = new FormData()
          fd.append('接口参数',文件数据)
        2.3 ajax发送请求 : 参数必须是formdata对象
       */
      //1.给file表单注册onchange事件 
      document.querySelector('#iptFile').onchange = function(){
        // console.log( this )//file表单
        //2.获取用户选择的文件
        /* 
        this.files : 伪数组,存储所有的选中的文件
        this.files[0] : 取出第一个文件
         */
        console.log( this.files[0] )
        //3.创建FormData对象
        let fd =  new FormData()
        //4. 调用append方法追加文件
        fd.append('avatar', this.files[0] )
        //5. ajax发送请求
        axios({
          url:'http://www.liulongbin.top:3009/api/upload/avatar',
          method:'post',
          /* 将formdata对象作为参数, fd对象会自动帮我们设置请求头,自动处理文件参数 */
          data:  fd,
        }).then(res=>{
          //成功回调
          console.log(res)
          //6.显示上传成功的图片
          document.querySelector('img').src =             `http://www.liulongbin.top:3009${res.data.url}`
        })
      }

    </script>
  </body>

自定义头像上传按钮

  <style>
    .thumb-box {
      text-align: center;
      margin-top: 50px;
    }

    .thumb {
      width: 250px;
      height: 250px;
      object-fit: cover;
      border-radius: 50%;
    }
  </style>
</head>

<body>
  <a href="http://www.baidu.com">百度</a>
  <div class="thumb-box">
    <!-- 头像 -->
    <img src="./images/cover.jpg" class="img-thumbnail thumb" alt="" />
    <div class="mt-2">
      <!-- 文件选择框 -->
      <!-- accept 属性表示可选择的文件类型 -->
      <!-- image/* 表示只允许选择图片类型的文件 -->
      <input type="file" id="iptFile" accept="image/*" style="display: none" />
      <br />
      <!-- 选择头像图片的按钮 -->
      <button class="btn btn-primary" id="btnChoose">
        选择 & 上传图片
      </button>
    </div>
  </div>

  <!-- label标签有一个独有的for属性, 它的值是 input元素的id 
        for作用: 让label与input建立关联。 点击了label相当于点击了input
    -->
  <label for="iptFile">
    <img src="./images/icon.png" width="60px" alt="">
  </label>


  <script src="./lib/axios.js"></script>

  <script>
    /* 自定义文件上传按钮思路
        1. 隐藏file表单  (设置display为none)
        2. 给自定义按钮注册点击事件 , 点击注册 file表单'默认'点击事件
            触发注册点击事件 :  dom元素.onclick()
            触发'默认'点击事件 :  dom元素.click()
    */

    //点击自定义按钮
    document.querySelector('#btnChoose').onclick = function () {
      //触发file表单点击事件即可
      /* 
      dom对象.onclick()   : 只能触发注册的点击事件, 没有注册则无法触发
      dom对象.click()     : 触发注册 + 触发默认点击事件  ( a标签、form按钮、file表单 )
      */
      document.querySelector('#iptFile').click()
    }

    //1.给file表单注册onchange事件 : 选择文件触发
    document.querySelector('#iptFile').onchange = function () {
      //2. 获取用户选择的文件   this.files[0] 
      //3. 创建FormData对象,把文件添加到fd对象
      let fd = new FormData()
      fd.append('avatar', this.files[0])
      //4.发送ajax
      axios({
        url: 'http://www.liulongbin.top:3009/api/upload/avatar',
        method: 'post',
        data: fd,
      }).then(res => {
        //成功回调
        console.log(res)
        //把服务器给的url显示到img标签 (可选)
        document.querySelector('img').src = `http://www.liulongbin.top:3009${res.data.url}`
      })

    }
  </script>

</body>

函数防抖

        /* 
        1.函数防抖 : 单位时间内,频繁触发一个事件, 以'最后一次'触发为准
        2.防抖应用场景: 输入框输入事件
        3.防抖流程 :
            3.1 声明一个全局变量存储定时器ID
            3.2 每一次触发交互的时候,先清除上一次定时器。 然后把本次事件处理代码放入定时器中
        */

        let timeID = null
        //输入框输入事件
        document.querySelector('input').oninput = function(){            
            //1.先清除之前的定时器
            clearTimeout(timeID)
            //2.开启本次定时器
            timeID = setTimeout(()=>{
                //function函数: this->window
                //箭头函数  this->上级this 表单
                console.log(`发送ajax,搜索内容是${this.value}`)
            },500) 
        }

函数节流

        /* 
        1.函数节流 : 单位时间内,频繁触发一个事件, 只会触发一次
        2.节流场景 : 解决高频事件 (滚动条事件高频触发)
        3.节流实现:
            3.1 声明一个全局变量存储触发时间   let lastTime = null
            3.2 每一次触发事件,获取当前时间   let currentTime = Date.now()
            3.3 判断 当前时间 与 上一次触发时间,是否超过间隔   currentTime-lastTime>=500
            3.4 如果超过触发间隔,则执行事件处理代码。 然后存储本次触发事件  lastTime =                currentTime
        */
        
        //声明一个全局变量存储触发时间
        let lastTime = null

        window.onscroll = function(){
            //1.每一次触发,先获取本次时间戳
            let currentTime = Date.now()
            //2.判断当前时间 与 上一次触发时间 是否超过间隔
            if( currentTime - lastTime >= 500 ){
                console.log( document.documentElement.scrollTop)
                //3.存储本次触发时间
                lastTime = currentTime
            }
            
        }