12. AJAX与Axios框架
12.1 AJAX基础
12.1.1 AJAX简介
AJAX(Asynchronous JavaScript and XML)是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。通过AJAX,网页应用程序能够快速地与服务器进行异步通信,从而提高用户体验。
AJAX的工作原理:
- 创建XMLHttpRequest对象:这是AJAX的核心,用于在后台与服务器进行数据交换。
- 发送请求:通过
XMLHttpRequest
对象发送请求到服务器。 - 服务器处理请求:服务器处理请求并生成响应。
- 接收响应:
XMLHttpRequest
对象接收服务器的响应。 - 更新网页:使用JavaScript更新网页的特定部分,而不是重新加载整个页面。
关键点:
- 异步通信:AJAX允许在不阻塞用户界面的情况下与服务器通信。
- 局部更新:只更新网页的特定部分,而不是整个页面。
- 支持多种数据格式:虽然名称中包含XML,但AJAX也可以处理JSON、HTML等其他数据格式。
AJAX技术广泛应用于现代Web开发中,使得网页应用更加动态和响应迅速。
12.1.2 第三方数据接口
第三方数据接口通常指的是由非原始服务提供商(即第三方)提供的用于访问和获取数据的接口。这些接口允许开发者通过编程方式从第三方服务获取数据,而无需直接与原始数据源交互。第三方数据接口可以涵盖各种类型的数据,包括但不限于天气数据、金融数据、社交媒体数据、地理位置数据等。
第三方数据接口通常以API(Application Programming Interface,应用程序编程接口)的形式提供,开发者可以通过HTTP请求(如GET、POST等)与这些API进行交互,获取所需的数据。API可能需要认证(如API密钥、OAuth令牌等)以确保数据的安全性和访问权限。
使用第三方数据接口的好处包括:
- 简化开发过程:开发者无需从头开始构建数据获取和处理系统,可以直接利用第三方提供的接口快速获取数据。
- 节省成本:通过使用第三方数据接口,开发者可以避免自行收集和维护数据的成本。
- 提高效率:第三方数据接口通常经过优化,能够提供高效的数据访问和处理能力。
常用的第三方数据接口有:
- 百度API
- 聚合数据API
- 天行数据API
- 极速数据API
- ... ...
下面案例需使用“天行数据API”与‘’聚合数据API‘’
-
申请“天气预报”接口:https://www.tianapi.com/apiview/72 (可直接跨域访问)
-
聚合数据:https://www.juhe.cn/
申请‘’新闻头条‘’接口:https://www.juhe.cn/docs/api/id/235 (不可直接跨域访问)
12.1.3 AJAX实例
XMLHttpRequest
是用于在浏览器和服务器之间进行异步通信的核心对象。它允许你发送HTTP请求并处理响应,而无需刷新整个页面。
<body>
<script>
// 创建XMLHttpRequest核心对象
let xhr = new XMLHttpRequest()
// 使用open方法创建http请求, 第一个参数为请求方式,第二个参数为请求的url
xhr.open('get', 'https://apis.tianapi.com/tianqi/index?key=d23f90897084de01dabffe2b8377cbeb&city=101020100&type=1')
// 向服务器发送请求
xhr.send(null)
// 监听XMLHttpRequest核心对象的状态
xhr.onreadystatechange = function() {
// 当readyState等于4时,表示服务器响应结束
if(xhr.readyState === 4) {
// 当status等于200时,表示请求成功
if(xhr.status === 200) {
console.log(xhr.responseText);
}
}
}
</script>
</body>
使用 open
方法初始化请求:
xhr.open('GET', 'https://example.com/api/data', true);
-
第一个参数是请求方法(如
GET
,POST
,PUT
,DELETE
等)。 -
第二个参数是请求的URL。
-
第三个参数是一个布尔值,表示请求是否异步(
true
表示异步,false
表示同步)。
readyState
是 XMLHttpRequest
对象的一个属性,用于表示请求的当前状态。它是一个整数,取值范围从 0 到 4,每个值代表不同的状态。以下是 readyState
的详细解释:
readyState 状态码
- 0 (UNSENT):未初始化
- 请求尚未初始化,
open
方法还未被调用。
- 请求尚未初始化,
- 1 (OPENED):已打开
open
方法已被调用,但send
方法还未被调用。请求头可以被设置。
- 2 (HEADERS_RECEIVED):已发送
send
方法已被调用,并且服务器已返回响应头。响应头和状态码已可用。
- 3 (LOADING):正在接收
- 响应体正在被接收。部分响应数据可能已可用,但尚未完成。
- 4 (DONE):完成
- 请求已完成,响应数据已完全接收。此时可以访问完整的响应数据。
status
是 XMLHttpRequest
对象的一个属性,用于表示HTTP请求的状态码。状态码是一个三位数的数字,表示请求的结果。以下是一些常见的状态码及其含义:
常见状态码
- 200 OK:请求成功。
- 404 Not Found:请求的资源未找到。
- 500 Internal Server Error:服务器内部错误。
- 403 Forbidden:请求被服务器拒绝。
- 301 Moved Permanently:请求的资源已永久移动到新位置。
- 302 Found:请求的资源临时移动到新位置。
12.1.4 AJAX的异步特性
AJAX(Asynchronous JavaScript and XML)的异步特性是其核心功能之一,它允许浏览器在不刷新整个页面的情况下与服务器进行通信。异步通信意味着浏览器可以在等待服务器响应的同时继续执行其他代码,从而提高用户体验和页面性能。
异步特性的关键点
- 不阻塞UI线程:
- 在AJAX请求发送后,浏览器不会等待服务器响应,而是继续执行后续代码。这避免了页面冻结和用户交互的中断。
- 事件驱动:
- AJAX请求的完成是通过事件触发的,例如
onreadystatechange
事件。当请求状态发生变化时,事件处理程序会被调用,从而可以在请求完成后处理响应数据。
- AJAX请求的完成是通过事件触发的,例如
- 并发处理:
- 可以同时发送多个AJAX请求,并且每个请求都可以独立处理其响应,而不会相互干扰。
异步处理的优势
- 提高用户体验:
- 用户可以在等待服务器响应的同时继续与页面交互,不会感到页面卡顿或无响应。
- 优化性能:
- 通过并发处理多个请求,可以更高效地利用网络资源,减少页面加载时间。
- 动态更新内容:
- 可以在不刷新整个页面的情况下,动态更新部分页面内容,提供更流畅的用户体验。
注意事项
- 异步请求可能会导致回调地狱(Callback Hell),即多层嵌套的回调函数,影响代码的可读性和维护性。可以使用
Promise
或async/await
来简化异步代码的编写。 - 处理错误和异常是异步编程的重要部分,确保在请求失败时提供适当的错误处理和用户反馈。
<body>
<script>
// 创建XMLHttpRequest核心对象
let xhr = new XMLHttpRequest()
// 使用open方法创建http请求, 第一个参数为请求方式,第二个参数为请求的url
// xhr.open('get', 'https://apis.tianapi.com/tianqi/index?key=d23f90897084de01dabffe2b8377cbeb&city=101020100&type=1')
// 向服务器发送请求
xhr.send(null)
let result
// 监听XMLHttpRequest核心对象的状态
xhr.onreadystatechange = function() {
// 当readyState等于4时,表示服务器响应结束
if(xhr.readyState === 4) {
// 当status等于200时,表示请求成功
if(xhr.status === 200) {
test(xhr.responseText)
}
}
}
function test(result) {
console.log(result)
}
</script>
</body>
12.2 axios框架
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 Node.js 中。它提供了简单的 API 来处理 HTTP 请求和响应,并且具有许多有用的功能,如拦截请求和响应、取消请求、自动转换 JSON 数据等。
axios框架中文网:https://www.axios-http.cn/
安装:
使用 npm:
$ npm install axios
使用 bower:
$ bower install axios
使用 yarn:
$ yarn add axios
使用 jsDelivr CDN:
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
使用 unpkg CDN:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
为了直接使用 require
导入预构建的 CommonJS 模块(如果模块打包器无法自动解析它们),axios官网提供了以下预构建模块:
const axios = require('axios/dist/browser/axios.cjs'); // browser
const axios = require('axios/dist/node/axios.cjs'); // node
12.2.1 get方式与post方式请求
GET 请求
用途:主要用于从服务器获取数据,不会对服务器上的资源进行修改。
参数传递方式:参数通过 URL 的查询字符串传递,例如:https://api.example.com/data?key1=value1&key2=value2
。参数会显示在 URL 中,对用户可见。
安全性:由于参数直接显示在 URL 中,因此不适合传递敏感信息,如密码、信用卡信息等。
缓存:可以被浏览器缓存,因此多次请求同一个 URL 可能会返回缓存的结果。
长度限制:由于参数在 URL 中传递,URL 的长度有限制(不同浏览器和服务器有不同的限制,通常在 2000 字符左右),因此 GET 请求的参数长度有限。
幂等性:是幂等的,即多次请求同一个 URL 的结果应该相同。
POST 请求
用途:主要用于提交数据,可能会对服务器上的资源进行修改。
参数传递方式:参数通过请求体(request body)传递,不会显示在 URL 中。参数对用户不可见。
安全性:参数在请求体中传递,相对更安全,适合传递敏感信息。
缓存:不会被浏览器缓存,每次请求都会发送到服务器。
长度限制:参数在请求体中传递,理论上没有长度限制(但实际上受限于服务器和客户端的配置)。
幂等性:不是幂等的,多次请求可能会导致不同的结果(如多次提交表单可能会创建多个资源)。
12.2.2 axios的get方式请求
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
// 向给定ID的用户发起请求
axios.get('https://apis.tianapi.com/tianqi/index?key=d23f90897084de01dabffe2b8377cbeb&city=101020100&type=1')
.then(function (response) {
// 处理成功情况
console.log(response);
})
.catch(function (error) {
// 处理错误情况
console.log(error);
})
.finally(function () {
// 总是会执行
});
/* // 上述请求也可以按以下方式完成(可选)
axios.get('https://apis.tianapi.com/tianqi/index', {
params: {
key: 'd23f90897084de01dabffe2b8377cbeb',
city: '101020100',
type: '1'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
})
.finally(function () {
// 总是会执行
});
*/
</script>
</body>
12.2.3 axios的post方式请求
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
axios.post('https://apis.tianapi.com/tianqi/index', transformRequest({
key: 'd23f90897084de01dabffe2b8377cbeb',
city: '101020100',
type: '1'
}))
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
</script>
</body>
当服务器端不能接受处理JSON数据时,需要转换函数:
<body>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
function transformRequest(data) {
let ret = '';
for (let it in data) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&';
}
return ret;
}
axios.post('https://apis.tianapi.com/tianqi/index', transformRequest({
key: 'd23f90897084de01dabffe2b8377cbeb',
city: '101020100',
type: '1'
}))
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
</script>
</body>
12.2.4 axios响应数据结构
<body>
<div id="container"></div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
function transformRequest(data) {
let ret = '';
for (let it in data) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&';
}
return ret;
}
axios.post('https://apis.tianapi.com/tianqi/index', transformRequest({
key: 'd23f90897084de01dabffe2b8377cbeb',
city: '101020100',
type: '7'
}))
.then(function (response) {
//console.log(response.data.result.list);
let arr = response.data.result.list;
let str = '';
for (let i = 0; i < arr.length; i++) {
str += `<p>日期: ${arr[i].date},天气:${arr[i].weather}`
}
// 将数据渲染到页面中
document.getElementById('container').innerHTML = str;
})
.catch(function (error) {
console.log(error);
});
</script>
</body>
12.2.5 axios的全局配置
Axios 提供了全局配置的功能,可以在创建实例之前进行全局配置,这样可以避免在每个请求中重复设置相同的配置项。全局配置通常包括基础 URL、超时时间、请求头等。
//全局配置
axios.defaults.baseURL = 'https://apis.tianapi.com/';
axios.post('tianqi/index', transformRequest({
key: 'd23f90897084de01dabffe2b8377cbeb',
city: '101020100',
type: '7'
}))
12.2.6 axios拦截器
Axios 拦截器允许你在请求或响应被处理之前拦截它们,从而可以在请求发送之前或响应接收之后执行一些操作。拦截器在处理认证、日志记录、错误处理等场景中非常有用。
Axios 提供了两种类型的拦截器:请求拦截器和响应拦截器。
请求拦截器
请求拦截器允许你在请求发送之前对其进行修改。例如,你可以在请求头中添加认证信息,或者在请求参数中添加一些公共参数。
响应拦截器
响应拦截器允许你在响应被 then 或 catch 处理之前对其进行修改。例如,你可以统一处理响应错误,或者在响应数据中添加一些额外的信息。
<body>
<div id="container"></div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
function transformRequest(data) {
let ret = '';
for (let it in data) {
ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&';
}
return ret;
}
axios.defaults.baseURL = 'https://apis.tianapi.com/';
// 添加请求拦截器
axios.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
console.log('拦截了请求');
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
axios.interceptors.response.use(function (response) {
// 2xx 范围内的状态码都会触发该函数。
// 对响应数据做点什么
console.log('拦截了响应');
return response;
}, function (error) {
// 超出 2xx 范围的状态码都会触发该函数。
// 对响应错误做点什么
return Promise.reject(error);
});
axios.post('tianqi/index', transformRequest({
key: 'd23f90897084de01dabffe2b8377cbeb',
city: '101020100',
type: '7'
}))
.then(function (response) {
//console.log(response.data.result.list);
let arr = response.data.result.list;
let str = '';
for (let i = 0; i < arr.length; i++) {
str += `<p>日期: ${arr[i].date},天气:${arr[i].weather}`
}
// 将数据渲染到页面中
document.getElementById('container').innerHTML = str;
})
.catch(function (error) {
console.log(error);
});
</script>
</body>
12.3 在Vue-cli中使用axios
安装axios:
npm install axios --save
使用:
<template>
<div>
<h1>上海市7天天气预报</h1>
<ul>
<li v-for="weather in weatherArr" :key="weather.date">
<p>{{ weather.date }} {{ weather.week }} {{ weather.weather }}</p>
</li>
</ul>
</div>
</template>
<script setup>
import axios from 'axios';
import { ref } from 'vue';
const weatherArr = ref([])
axios.get('https://apis.tianapi.com/tianqi/index?key=d23f90897084de01dabffe2b8377cbeb&city=101020100&type=7')
.then((response) => {
// 处理成功情况
weatherArr.value = response.data.result.list
})
.catch(function (error) {
// 处理错误情况
console.log(error);
})
.finally(function () {
// 总是会执行
});
</script>
<style></style>
12.4 在Vue-cli中实现跨域访问
12.4.1 什么是跨域访问
12.4.1.1 同源策略
同源策略(Same-Origin Policy)是一种重要的安全机制,它用于限制一个源(origin)的文档或脚本如何与另一个源的资源进行交互。这种策略帮助防止恶意网站读取或操作另一个网站的数据,从而保护用户免受跨站脚本攻击(XSS)和跨站请求伪造(CSRF)等安全威胁。
同源的定义
两个URL被认为是同源的,当且仅当它们具有相同的协议(protocol)、主机(host)和端口(port)。具体来说:
- 协议:例如
http
或https
- 主机:例如
www.example.com
- 端口:例如
80
(对于http)或443
(对于https)
如果任何一个部分不同,那么这两个URL就被认为是不同源的。
同源策略的限制
同源策略主要限制以下几种行为:
- 无法读取不同源的Cookie、LocalStorage和IndexedDB:浏览器会阻止脚本访问不同源的这些数据存储。
- 无法获取不同源的DOM:例如,一个页面无法通过JavaScript访问另一个页面的DOM内容。
- 无法进行跨域XHR(XMLHttpRequest)和Fetch请求:默认情况下,浏览器会阻止脚本向不同源的服务器发送XHR或Fetch请求。
URL | 结果 | 原因 |
---|---|---|
https://store.company.com/dir2/other.hteml | 同源 | 只有路径不同 |
https://store.company.com/dir/inner/anthor.html | 同源 | 只有路径不同 |
https://store.company.com/secure.html | 失败 | 协议不同 |
http://store.company.com:81/dir/etc.html | 失败 | 端口不同(https://默认端口是80) |
http://news.company.com/dir/other.html | 失败 | 主机不同 |
12.4.1.2 跨域访问
跨域访问(Cross-Origin Access)指当一个客户端访问服务器端时,如果客户端的协议、IP端口三者之间的任意一个,与服务端的协议不同时,即为跨域访问。
注意:为了安全。AJAX默认不允许跨域访问
<template>
<div>Cross</div>
</template>
<script setup>
import axios from 'axios';
axios.get('http://v.juhe.cn/toutiao/index?key=778d4201a6a859e7a')
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
</script>
<style></style>
运行上面代码,在浏览器控制台中会出现“跨域访问”错误
Access-Control-Allow-Orgin访问控制允许源
12.4.1.3 解决AJAX跨域问题
AJAX(Asynchronous JavaScript and XML)是一种在Web应用中进行异步数据交互的技术。然而,由于浏览器的同源策略(Same-Origin Policy)限制,直接进行跨域AJAX请求会被阻止。为了解决AJAX跨域问题,有几种常见的解决方案:
- CORS(跨域资源共享)
CORS是一种基于HTTP头的机制,服务器在响应头中添加Access-Control-Allow-Origin
字段,允许特定的源进行跨域请求。这是最常用和推荐的跨域解决方案。
- JSONP(JSON with Padding)
JSONP是一种利用<script>
标签的src属性进行跨域请求的技术。由于<script>
标签不受同源策略的限制,可以通过动态创建<script>
标签来请求不同源的数据。JSONP仅支持GET请求。
- 代理服务器
在同源的服务器上设置一个代理,客户端先请求同源的代理服务器,然后代理服务器再去请求目标服务器。这种方式可以绕过浏览器的同源策略限制。
CopyInsert
- WebSockets
WebSockets是一种在单个TCP连接上进行全双工通信的协议。由于WebSockets不受同源策略的限制,可以用于跨域通信。
12.4.2 使用Vue-cli实现跨域访问
vue.config.js 配置代理:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer: {
proxy: {
'/juheNews': {
target: 'http://v.juhe.cn/toutiao/index', //需要跨域的url
ws: true, // 使用websockets协议进行代理
changeOrigin: true, // 设置允许跨域
pathRewrite: {
'^/juheNews': '' // 重写路径
}
}
}
}
})
Cross.vue:
<template>
<div>Cross</div>
</template>
<script setup>
import axios from 'axios';
axios.get('/juheNews?key=778d4201a6a859e7a4972959c86c6f1f&type=top&page=20&page_size=30&is_filter=0')
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
</script>
<style></style>
标签:function,axios,请求,error,---,12,https,Vue3,response
From: https://www.cnblogs.com/yishengwanwuzhao/p/18393237