前端战五渣:”啊!贾克斯?武器大师?Ajax!XMLHttpRequest“

啥都不说了,挺华为就完事了,山姆大叔有点过度了,我相信华为能挺过来javascript

如今该我了!

啊,贾克斯???如今从事前端的小伙伴不可能不知道这个,若是真不知道这个词,那我以为你还称不上前端开发🙄css

此贾克斯非彼贾克斯,前端说的啊贾克斯是Asynchronous javaScript + XML的简写,Ajax在很大程度上让前端发展加快了脚步,他的出现和使用,但是说是前端史上的里程碑html

Ajax横空出世,打破了先后端交互的时候须要从新加载页面,就是整页刷新,咱们能够经过Ajax技术直接在页面不刷新的状况下,发出请求,获取返回数据,而后经过js操做Dom更改页面内容。前端

也是Ajax出现了之后,才促成了日后的先后端分离,再也不是前端只负责切图,只是给后端同窗提供模板,而后数据由后端同窗添加上。咱们前端今后也能够再也不依赖后端同窗模板套数据了,咱们本身就能够完成。java

那咱们是如何实现这个无刷新获取数据呢,这就要基于一个对象了————XMLHttpRequestjquery

开打!开打!

Ajax说白了不是新技术,只是一种解决方案,跟jsonp差很少,是基于XMLHttpRequest对象的一个获取后端数据的方案,那咱们来看看怎么写的吧(本文不涉及兼容ie等部分浏览器,走主流)ios

get请求

(() => {
  // 获取页面上须要发请求的按钮
  let btn = document.querySelector('.getAjaxBtn'); 
  // 添加事件
  btn.addEventListener('click', createXHR)
  // 咱们ajax的主体函数
  function createXHR() {
    // new一个XMLHttpRequest实例
    var xhr = new XMLHttpRequest();
    // 第一步使用open方法,接收三个参数
    // 第一个参数是请求方法名(get,post等)
    // 第二个参数是须要请求的接口地址
    // 第三个参数是设置请求是不是异步,通常都是都是发送异步请求,同步请求可能会阻塞页面
    // 咱们先来看同步请求
    xhr.open('get', '/api/get', false);
    // open方法只是设置参数,并不会发送请求
    // 而请求是由send()方法发送的,而且接收一个参数,就是须要发送到服务端的数据
    // 若是没有须要发送到服务端的数据,必须传入null,由于有些浏览器不准要这个参数
    xhr.send(null)
  }

})()
复制代码

这样写的话,咱们就在一个按钮上绑定了一个发送get请求的方法,只要咱们点击这个按钮,就会发送请求,那咱们来看看是什么效果 面试

其实很简单是否是,没错,这样咱们确实就已经发送了一个get请求了,那咱们发送请求是为了什么呢,固然是为了获取到数据,那咱们看到接口已经返回了字符串'恭喜你,你发送了一个get请求,真棒!',那咱们怎么能拿到这个数据呢,看下面ajax

拿到返回数据

其实咱们在收到服务端响应的时候,就已经拿到了数据,响应的数据会自动填充到XHR对象中,但咱们何时才能知道这个数据已经填充到XHR对象中呢??这个时候咱们就须要一个相似于监听函数的事件————readystatechange事件,z这个事件当readystate状态改变,就会执行一次。咱们还须要一个知道请求发送状态的属性————readystate,还有一个请求状态码属性————statusjson

状态码就是200、404以及500这种的,在这就不细说了,主要说说readystate有什么状态:

  • 0: 未初始化。还没有调用open()方法
  • 1: 启动。已经调用open()方法,但还没有调用send()方法
  • 2:发送。已经调用send()方法,但还没有接收到响应
  • 3:接收。已经接收到部分相应数据
  • 4:完成。已经接收到所有响应数据,并且已经能够在客户端使用了

看了一下这接个状态,好像咱们如今须要的是4这个状态,接收到了所有的数据,而后咱们再作一个逻辑处理,上面的请求咱们是同步请求,如今咱们改改装一下

(() => {
  // 获取页面上须要发请求的按钮
  let btn = document.querySelector('.getAjaxBtn'); 
  // 添加事件
  btn.addEventListener('click', createXHR)
  // 咱们ajax的主体函数
  function createXHR() {
    // new一个XMLHttpRequest实例
    var xhr = new XMLHttpRequest();
    // 第一步使用open方法,接收三个参数
    // 第一个参数是请求方法名(get,post等)
    // 第二个参数是须要请求的接口地址
    // 第三个参数是设置请求是不是异步,通常都是都是发送异步请求,同步请求可能会阻塞页面
    // 咱们先来看同步请求
    xhr.open('get', '/api/get', true);
    // 咱们为xhr添加一个readyState值改变就执行的监听事件
    // 这个事件还必须写在send()方法前面
    xhr.onreadystatechange = function () {
      // 当readyState值为4就是接收到了所有返回数据,而且http状态码是200多的成功,或者是304的缓存,这时候就判断已是成功拿到了应该返回的数据
      if (xhr.readyState === 4 ) {
        if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304 ) {
          // 输出数据。responseText是做为响应主体被返回的文本
          alert(xhr.responseText)
        } else {
          alert('请求不成功')
        }
      } 
    }
    // open方法只是设置参数,并不会发送请求
    // 而请求是由send()方法发送的,而且接收一个参数,就是须要发送到服务端的数据
    // 若是没有须要发送到服务端的数据,必须传入null,由于有些浏览器不准要这个参数
    xhr.send(null)
  }

})()
复制代码

这样咱们就成功的拿到了返回的数据而且弹出来了,咱们不只拿到数据能够弹出,咱们就能够进行一些更厉害的逻辑处理或者改变页面内容了。

固然了,也许你get请求的时候须要发送一些数据给服务端,多是什么页码或者页面须要多少条数据等,咱们这个时候只要在open()方法中传入的url上面拼上就好了,相似/api/get?pageNum=1&pageSize=20这样的url。

咱们写的服务端就是返回请求中的数据,咱们也能看到,咱们也收到了返回来的数据了

post请求

post请求,咱们应该接触过form的表单提交,咱们post请求传输的数据必须是通过encodeURIComponent转码的,并且当咱们接收到一个json对象,咱们须要将他进行转换

(() => {
  let btn = document.querySelector('.getAjaxBtn'); 
  btn.addEventListener('click', createXHR);
  // 咱们须要转换的数据,真实场景咱们应该是传进来的,或者是获取到的用户输入的数据
  let data = {
    method: 'post',
    a: 'a',
    b: 123,
  }
  function createXHR() {
    var xhr = new XMLHttpRequest();
    xhr.open('post', '/api/post', true);
    xhr.onreadystatechange = function () {
      if (xhr.readyState === 4 ) {
        if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304 ) {
          alert(xhr.responseText)
        } else {
          alert('请求不成功')
        }
      } 
    }
    // 模仿表单提交,设置content-type,咱们须要从新设置请求头,让服务端能知道咱们传的是个什么数据
    xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
    // send()方法须要传入的数据应该通过处理
    xhr.send(transformData(data))
  }
  // 处理传入json对象转换格式
  /** * 例如这个样的json * { method: 'post', a: 'a', b: 123, } */
  // 转换格式为
  // method=post&a=a&b=123
  // 这样
  function transformData(data) {
    let newData = [];
    for (let key in data) {
      newData.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
    }
    return newData.join('&')
  }

})()
复制代码

上面就是咱们进行的post请求,咱们能看到咱们发送了一了个Form Data,而后服务端拿到了这个数据,而且咱们拿到了会返回来的数据,也就是咱们发送给服务端的数据

还有谁!

固然除了我上面说到的一些属性和方法,XHR还有不少我没有介绍到的方法和属性,这里就说一下几个经常使用的吧

  • XMLHttpRequest.timeout: 这个就是能够设置请求超时,设置一个时间,单位为毫秒,若是请求时间超过设置时间,直接抛出异常
  • XMLHttpRequest.withCredentials: 这个属性是看咱们需不须要发送cookie的,由于若是是跨域请求,通常请求是不会带上cookie,须要咱们手动设置这个属性
  • XMLHttpRequest.abort(): 这个方法咱们用来终止请求,固然是在请求发送并无返回的时候
  • XMLHttpRequest.setRequestHeader(): 这个咱们刚才有用到过,就是设置请求头,更改一些咱们须要的设置

把他们也算上!

若是咱们这么写,咱们会发现很麻烦,并且若是咱们没有考虑周全,这个请求方法会很糟糕,隐藏一些未知问题

技术,向来都是为了提升效率,或者也能够说是为懒人研究的

如今已经有很好的成熟的开源库替咱们封装好了ajax请求方法,例如“尚能饭否的jQuery”以及随着框架模块大放异彩的“Axios”,他们的使用方法相对简单不少,也不用咱们本身去处理一些逻辑问题,边界问题。

jQuery & Axios

咱们来看看这两个是多么简单实现的

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <title>Ajax</title>
</head>
<body>
  <button class="postAxiosBtn">发送axios post请求</button>
  <button class="getAxiosBtn">发送axios get请求</button>
  <button class="postJqueryBtn">发送jQuery post请求</button>
  <button class="getJqueryBtn">发送jQuery get</button>
  <script> var postAxiosBtn = $('.postAxiosBtn'), getAxiosBtn = $('.getAxiosBtn'), postJqueryBtn = $('.postJqueryBtn'), getJqueryBtn = $('.getJqueryBtn'); postAxiosBtn.click(() => { axios.post('/api/post', { data: { method: 'post', a: 'a', b: 123, } }).then(res => { console.log(res) }) }) getAxiosBtn.click(() => { axios.get('/api/get', { params: { pageNum: 1, pageSize: 20 } }).then(res => { console.log(res) }) }) postJqueryBtn.click(() => { $.post('/api/post', {method: 'post', a: 'a', b: 123}, function (data, status) { console.log(data) console.log(status) }) }) getJqueryBtn.click(() => { $.get('/api/get', {pageNum: 1, pageSize: 20}, function (data, status) { console.log(data) console.log(status) }) }) </script>
</body>
</html>
复制代码

封装库使用起来就是这么简单!!!

哼,一个能打的都没有!

fetch

想来你们也都知道fetch这个api了,js新出的一个api,对标的就是XMLHttpRequest,可是相比于XMLHttpRequest,fetch的使用很人性化了,并且自带promise语法,咱们不用再用什么回调的方法了,可是fetch再去跟axios这种封装XMLHttpRequest的库来讲,使用方法上还有有很大的差距吧。

但我相信之后封装fetch这种的库会愈来愈多的,如今虽然有,可是我感受用的人尚未要使用axios那种程度😜

总结

如今已经不多会用到纯手写原生Ajax了,都会用已经写好的封装库了,可是面试的时候不乏也会遇到让你手写的,这就很头疼了

尤大的回答不无道理,可是能说上来或者手写原生Ajax的人,绝对是对只是有着一种执着

知其然也得知其因此然,写伪代码我感受也是说的过去的,起码对大的思路要了解,一些api接不住无所谓,js、css那么多属性,方法,要是都记下来确定是不可能的,可是仍是能知道有这个东西的存在,查的时候也好查,是否是🤠


我是前端战五渣,一个前端界的小学生。

相关文章
相关标签/搜索