• JS Ajax 封装


    一、 什么是Ajax?

    Ajax(Asynchronous JavaScript And XML)是2005年新出现的技术,它的出现是为了解决这样一个场景:整个页面中,只有一小部分的数据需要进行更新,按照传统的前后端交互,我们需要向服务器请求该网页的所有数据,然后再在客户端重新渲染,这无疑是非常低效的操作。因此,Ajax就可以做到只向服务器请求我们想要的那一小部分数据,而不用请求全部数据,进而在刷新整个页面的前提下更新那部分的数据。

    举个例子,我们去饭店吃饭,然后点了一桌子菜,后来发现其中有一道菜太咸了,因此我们只需要让服务员端回去给厨师重新做这一道菜再拿回来就行了。

    吃饭事件数据更新
    我们客户端
    菜品页面所有的数据
    服务员ajax对象
    厨师服务器

    当我们发现有一道菜太咸了,不需要让厨师把所有的菜重新做一遍,只要让服务员拿这一道菜回去给厨师重做这一操作就相当于让ajax对象向后端请求那一小部分数据再拿回来更新页面而无需刷新整个页面。

    二、 Ajax的优缺点?

    当我们发现有一道菜太咸了,不需要让厨师把所有的菜重新做一遍,只要让服务员拿这一道菜回去给厨师重做这一操作就相当于让ajax对象向后端请求那一小部分数据再拿回来更新页面而无需刷新整个页面。

    2.1 优点

    • 浏览器默认支持(一般浏览器都是支持JavaScript的)
    • 提高用户体验(不需要刷新整个页面,而只需要局部刷新)
    • 提高页面的性能(只需要请求部分数据,所以数据量就明显下降了)

    2.2 缺点

    • 破坏了浏览器的前进和后退功能(Ajax不会改变网页URL,因此不会在浏览器记录前后页面)
    • 对搜索引擎的支持较弱(搜索引擎无法监测到JS引起的数据变化)

    三、 Ajax的使用

    Ajax的基本流程:创建XHR对象 => 发送数据 => 接收数据

    3.1 状态码

    既然Ajax涉及到前后端的数据交互,那么我们就先来简单的看一下几种类型的状态码,如下表:

    状态码含义
    100 ~ 199连接含义
    200 ~ 299各种成功的请求
    300 ~ 399重定向
    400 ~ 499客户端错误
    500 ~ 599服务端错误

    3.2 xhr的基本使用

    在使用xhr之前,我们要创建一个xhr的实例对象:

    let xhr = new XMLHttpRequest()
    
    • 1

    然后再调用xhr对象上的 open() 方法,表示创建一个请求。
    open() 方法接收三个参数:

    • 第一个参数: 请求的类型(例如get 、post)
    • 第二个参数: 请求的URL
    • 第三个参数: 是否异步发送请求(默认为true)
    // 创建了一个Ajax请求
    xhr.open('get', 'example.php', 'true')
    
    • 1
    • 2

    光调用了 open() 方法还不够,它只是创建了一个请求,但还没有发送请求,因此我们还要调用xhr对象上的另一个方法,即 send() 方法,表示将请求发送给目标URL

    send() 方法接收一个参数:

    • 第一个参数: 作为请求主体发送的数据(例如post请求携带的数据)
    // 我们上面创建的是get请求,因此send()方法无需传参
    xhr.send()
    
    • 1
    • 2

    请求发送出去后,客户端需要接收服务器响应回来的数据,xhr对象中有一些属性,它们存储着服务端返回来的一些数据信息,如下表所示:

    属性名含义
    response Text服务端返回的文本信息
    responseXML服务端返回的XML DOM 文档
    statusHTTP 状态码
    status TextHTTP状态码说明
    readyStatexhr对象的请求响应阶段

    既然我们要获取服务端返回的数据,我们就要知道服务端是何时返回数据的,这就可以通过上面表格中的 readyState 属性来判断了
    readyState 属性一共有5个值,分别表示不同的请求响应阶段:

    • 0: 还未创建请求,即未调用 open() 方法
    • 1: 已调用 open() 方法,但未发送 send() 方法
    • 2: 已调用send() 方法,但未接收到响应
    • 3: 已接收到部分响应
    • 4: 已接收到全部的响应

    同时,xhr对象可以绑定一个 readystatechange 事件,每当 readyState 属性发生改变,都会触发该事件,因此,该事件在一次请求中会被多次触发

    xhr.onreadystatechange = function() {
    	console.log('readyState属性发生改变了')
    }
    
    • 1
    • 2
    • 3

    所以,我们可以在 readystatechange 事件中判断一下 readyState 属性是否为 4,即是否已经接收所有的响应,然后还可以再继续判断一下 status 属性,看看状态码是否为 200,当上述都成立了,我们再去 responseText 属性 或 responseXML 属性中获取响应数据

    xhr.onreadystatechange = function() {
    	// 判断是否已接收所有响应
    	if(xhr.readyState === 4) {
    		// 判断状态码是否为200
    		if(xhr.status === 200) {
    			console.log(xhr.responseText)
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3.3 ajax原生封装:

    //封装一个ajax请求
    function ajax(options) {
      //创建XMLHttpRequest对象
      const xhr = new XMLHttpRequest()
    
      //初始化参数的内容
      options = options || {}
      options.type = (options.type || 'GET').toUpperCase()
      options.dataType = options.dataType || 'json'
      // 处理参数
      let str = ''
      let params = options.data;
      for (let key in params) {
        str += key + '=' + params[key] + '&'
      }
      params = str.slice(0, str.length - 1)
    
    
      //发送请求
      if (options.type === 'GET') {
        xhr.open('GET', options.url + '?' + params, true)
        xhr.send(null)
      } else if (options.type === 'POST') {
        xhr.open('POST', options.url, true)
        // post 请求需要设置请求头 模仿表单请求
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
        xhr.send(params)
      }
      //接收请求
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          let status = xhr.status
          if (status >= 200 && status < 300) {
            options.success && options.success(xhr.responseText, xhr.responseXML)
          } else {
            options.fail && options.fail(status)
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    3.3.1 触发GET请求:

    上面也讲解了Ajax请求的简单应用,同时也是拿 get 请求来举得例子,因此这里我就不多做说明,唯一要讲的就是,get请求所携带的数据是明文的,大小只有4k左右,而且它是写在URL的 ? 后面的,例如这样 example.php?query=4&em=0,所以若是我们要在发送get请求时携带数据,只需要在调用 open() 方法时,将数据写在第二个参数的URL的 ? 后面即可

    let btn = document.querySelector('.btn')
    btn.addEventListener('click', function () {
      ajax({
        type: 'get',
        dataType: 'json',
        data: { uid: '64dcd451a2d7172b77c03768', aid: "64db6361c57b44a4c47712af" },
        url: 'http://localhost:3456/wyc/getUser',
        success: function (text, xml) {//请求成功后的回调函数
          console.log(JSON.parse(text))
        },
        fail: function (status) {请求失败后的回调函数
          console.log(status)
        }
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    接收结果:
    在这里插入图片描述
    在这里插入图片描述

    3.3.2 调用POST请求:

    发送post请求的过程几乎和get请求一样,唯一不一样的是数据的传递。大家都知道post请求的数据是放在请求体中的,因此我们需要调用xhr对象上的 setRequestHeader() 方法来模仿表单提交时的内容类型
    该方法传入的参数比较固定,代码如下

    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
    
    • 1

    然后我们上面也说过,send() 方法接收的一个参数是请求主体发送的数据,所以我们的post请求要发送的数据就要作为该方法的参数,代码如下:

    xhr.send('query=4&em=0')
    
    • 1

    完整post请求:

    let btn = document.querySelector('.btn')
    btn.addEventListener('click', function () {
      ajax({
        type: 'post',
        dataType: 'json',
        data: { uid: '64dcd451a2d7172b77c03768', aid: "64db6361c57b44a4c47712af" },
        url: 'http://localhost:3456/wyc/attention',
        success: function (text, xml) {//请求成功后的回调函数
          console.log(JSON.parse(text))
        },
        fail: function (status) {请求失败后的回调函数
          console.log(status)
        }
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    请求结果:
    在这里插入图片描述
    在这里插入图片描述

    四、Ajax的约束

    了解过同源策略以后,我们来看看如何让Ajax不受同源策略的限制而成功发送请求。CORS(跨域资源共享)要求我们在发送请求时自定义一个HTTP头部与服务器进行沟通,我们只需要设置一个名为 Origin 的头部,值为当前页面的源信息(协议、域名、端口),例如 Origin : http://example.com ;然后服务器需要设置一个名为 Access-Control-Allow-Origin 的响应头部,其值为允许跨域访问的源信息,若服务器设置的 Access-Control-Allow-Origin 与我们设置的 Origin 相同,则表示服务器允许我们跨域请求其资源,或者服务器可以将 Access-Control-Allow-Origin 值设为 *,此时表示允许任何域向其发送请求并且不受同源策略的限制。

  • 相关阅读:
    ES (ElasticSearch) 简易解读(三)企业级日志分析ELK架构的搭建与使用
    Groovy XML JSON
    Goby 漏洞发布|Revive Adserver 广告管理系统 adxmlrpc.php 文件远程代码执行漏洞(CVE-2019-5434)
    【2021研电赛】基于动态无线充电技术的自动驾驶小车
    ASP.NET Core依赖注入系统学习教程:容器对构造函数选择的策略
    攻防世界----unfinish
    计算机视觉岗暑期实习应聘总结
    .NET 6 实现滑动验证码(二)、基本数据
    如何导出带有材质的GLB模型?
    Visual Studio 调试时加载符号慢
  • 原文地址:https://blog.csdn.net/wu_2004/article/details/133064583