AJAX学习笔记

85 阅读5分钟

1.原生的AJAX

1.1AJAX简介:

ajax全称为Asychronous Javascript And XML就是异步的js和XML

通过AJAX可以在浏览器中向服务器发送异步请求,它最大的优势是能够实现页面无刷新获取数据,AJAX不是新的编程语言,而是一种将现有的标准组合在一起使用的新方式

1.2XML的简介

  1. XML是可扩展标记语言
  2. XML被设计用来传输和存储数据
  3. XML和HTML类似,不同的是HTML中都是预定义标签,而XML中没有预定义标签,全都是自定义标签,用来表示一些数据 比如用XML表示一个学生数据:
<student>
    <name>张三</name>
    <age>18</age>
    <gender></gender>
</student>

但是现在已经被JSON取代

{"name":"张三","age":"18","gender":"男"}

1.3AJAX的特点

优点:

  1. 可以无需刷新页面而与服务器端进行通信
  2. 允许你根据用户事件来更新部分页面内容

缺点:

  1. 没有浏览历史,不能回退
  2. 存在跨域问题
  3. SEO(搜索引擎优化)不友好

2.AJAX的使用

2.1ajax发送请求的步骤

核心对象:XMLHttpRequest,AJAX的所有操作都是通过该对象进行的

使用步骤:

  1. 创建XMLHttpRequest实例对象
const xhr = new XMLHttpRequest()
  1. 设置请求信息(指定发送请求的方法method和地址url)
xhr.open(method.url) // 配置请求
xhr.setRequestHeader(key,value) // 设置请求头(可选)
  1. 发送请求
xhr.send(body) // get请求不传body参数,只有post请求使用
  1. 接收响应(对xhr的状态进行监听,获取响应数据)
// onreadystatechange当状态准备改变时
xhr.onreadystatechange = ()=>{
    if(xhr.readyState === 1) {
        //此处也可设置请求头
    }
    // 获取请求成功的响应数据
    if(xhr.readyState === 4 && (xhr.status >= 200 && xhr.status <= 300)) {
        console.log(xhr.response)
    }
}

xhr内部有五种状态:值分别为0、1、2、3、4。 xhr实例对象,在实例被创建出来的那一刻状态就为0,当数据接收完毕之后状态会变为4

5种状态值分别为:

0: 实例化出来的那一刻状态就是0,初始状态

1: open已经调用了,但是send还没有调用,此时可以修改请求头内容

2: send已经调用了,此时已经无法修改请求头了

3: 已经回来了一部分的数据,小的数据会在此阶段一次性接收完毕,较大的数据有待进一步接收,响应头回来了

4: 数据全部接收完毕

2.2ajax发送get请求

get请求携带参数有两种方式:queryparams

// query参数
xhr.open('GET','http://127.0.0.1:8080/xxx?name=张三&age=18')
// params参数
xhr.open('GET','http://127.0.0.1:8080/xxx/张三/18')
  1. 形如:xxx/xxx/key=value&key2=value2就是query参数的urlencoded编码形式
  2. 形如:/xxx/xxx/张三/18就是params参数

2.3ajax发送post请求

post请求可以携带query参数,params参数,body参数

// 如果post请求携带的是header参数,有如下两种方式
xhr.open('POST',http://127.0.0.1:8080/xxxx?name=张三&age=18)
xhr.open('POST',http://127.0.0.1:8080/xxxx/张三/age=18)
// 如果post请求携带的是body参数,则需要使用xhr.send()去传递参数
xhr.open('POST',http://127.0.0.1:8080/xxxx)
// 注意此处需要设置一个特殊的请求头
// 追加响应头用于表示携带请求体参数的编码形式 ---urlencoded
xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded')
xhr.send('name=张三&age=18') // 携带urlencoded编码形式的请求体参数

// 以json形式
const person={name:'张三',age:18}
// 追加响应头用于表示携带请求体参数的编码形式 ---json
xhr.setRequestHeader('Content-type','application/json')
xhr.send(JSON.stringify(person)) // 携带json形式的请求体参数

2.4ajax解析json数据

  1. 在接收到响应数据之后,使用JSON.parse()方法将json数据转一下
 xhr.onreadystatechange= ()=>{
     if(xhr.readyState === 4){
           if(xhr.status >=200 && xhr.status <= 300){
                  console.log(xhr.response)
                  const result = JSON.parse(xhr.response)
                  console.log('result',result)
           }
     }
}

2.配置xhr.responseType = 'json',能够自动解析json形式的响应数据

// 配置解析json字符串,不用手动加JSON.parse()
xhr.responseType = 'json'

第二种方法的优点:

  1. 不用手动添加JSON.parse()方法去转化json字符串
  2. 当返回的字符串不是符合标准的json字符串时,不会报错,返回一个null值说明解析不成功

2.5请求异常与请求超时的处理

// 配置请求异常的提示(比如断网..)
xhr.onerror = () => {
    alert('当前网络不稳定,请稍后重试')
}
//设置请求超时时间
xhr.timeout = 2000
// 超时后提示用户
xhr.ontimeout = ()=>{
    alert('当前请求超时,请稍后再试')
}

3.jQuery封装的ajax

// 使用jQuery发送ajax_get(完整版)
$.ajax({
       url: 'http://127.0.0.1:8080/xxx', // 请求地址
       method: 'GET', // 请求方法(不写默认是get请求)
       data: { xx: 'xxx' }, // 请求参数
       dataType:'json', // 配置响应数据格式
       success: (res) => {
                   console.log('res',res);
               }, // 请求成功后的回调
       error: () => {
               console.log('请求出错了')
           } // 请求失败后的回调
       })
// 精简版写法(参数1:url,参数2:携带的数据,参数3:请求成功的回调,参数4:响应数据格式)
/* $.get('http://127.0.0.1:8080/xxx',{xx:'xxx'},(res)=>{
       console.log(res)
},'json') */

// (post请求同上)

4.跨域与同源策略

4.1同源策略

同源策略(Same-OriginPolicy)是由Netscape 公司提出,是浏览器的一种安全策略,现在所有支持javaScript的浏览器都会使用这个策略,违背同源策略被称为跨域

同源的规则是:协议,域名,端口号必须完全相同 比如一个网址: http://127.0.0.1:8080, http则为协议,127.0.0.1为域名或者主机名,8080为端口号

如下表举例,分析请求是否会成功(假设已有网站地址:http:study.cn)

请求地址形式结果
study.cn/test/a.html协议,域名,端口号均相同成功
study.cn/test/user/a…协议,域名,端口号均相同成功
a.study.cn/test/a.html协议不相同失败
study.cn:8080/test/a.html端口号不相同失败
study.cn/test/a.html协议不相同失败

4.2解决跨域问题

4.2.1.jsonp方式

jsonp(JSON with padding),是一个非官方的跨域解决方案,纯粹拼接程序员们的聪明才智开发出来的,它只支持get请求

在网页中有一些标签天生具有跨域的能力,比如:img link iframe script等,jsonp就是利用了script标签发送请求不受同源策略的限制的特点

// 使用后nodejs创建一个简单的服务器,配置一个get请求的路由

const express  = require('express')
const app = express()
// 响应jsonp请求
app.get('/test_jsonp',(req,res)=>{
    console.log('有人请求test_json了')
    const {callback} = req.query
    const person = {name:'张三',price:'18'}
    res.send(`${callback}(${JSON.stringify(person)})`)
})
app.listen(8080,()=>{
    console.log('server is runing at http:127.0.0.1:8080')
})
// 前端页面
<body>
    <button id="btn">点我获取数据</button>
    <script>
        const btn = document.getElementById('btn')
        btn.onclick=()=>{
            // 1.创建script节点
            const scriptNode = document.createElement('script')
            // 2.给节点指定src属性(请求地址)
            scriptNode.src = 'http://127.0.0.1:8080/test_jsonp?callback=demo'
            // 3.将节点放入页面
            document.body.appendChild(scriptNode)
            // 4.定义一个函数
            window.demo = function(a){
                console.log(a)
            }
            // 5.移除已经使用过的script节点
            document.body.removeChild(scriptNode)
        }
    </script>
</body>

就类似于前端定义好一个function,后端通过接口返回数据调用该function

// 使用jQuery封装的jsonp
const btn = $('#btn')
btn.click( ()=>{
    $.getJSON('http://127.0.0.1:8080/test_jsonp?callback=?',{},(res)=>{
        console.log(res)
    })
})

4.2.2.cors配置响应头

cors(Cross-Origin Resource Sharing),跨域资源共享,需要后端配置一组响应头

res.setHeader('Access-Control-Allow-Origin','允许跨域的网站')

注意:

  1. 如果只配置Access-Control-Allow-Origin,并不能完整的解决问题,它返回的响应头将会有缺失,还需要配置res.setHeader('Access-Control-Expose-Headers','*'),返回其它所有的响应头
  2. 如果使用PUT或者DELETE复杂请求,在请求发起之前,会进行一次预请求,相当于会发两次请求,解决方法如下,在写的put路由之前,再添加一个options
app.options('/test_put',(req,res)=>{
    res.setHeader('Access-Control-Allow-Origin','允许跨域的网站')
    res.setHeader('Access-Control-Expose-Headers','*') // 返回其他的请求头
    res.setHeader('Access-Control-Allow-methods','*') // 设置允许请求的方法,*标识所有
    res.send()
})