1. axios
axios官方文档
异步库axios和mockjs模拟后端数据,axios是一个基于promise的HTTP库,使用npm i axios。在main.js中引入,需要绑定在Vue的prototype属性上,并重命名。
(1)main.js文件引用
import http from 'axios'
Vue.prototype.$http = http
1.1. axios简单例子
(1)在home的index.vue中添加mounted
/**
* 拦截器部分
* @param instance
*/
interceptors(instance) {
// 添加请求拦截器
instance.interceptors.request.use(function (response) {
console.log("添加请求拦截器:", response)
// 在发送前做什么
return response;
}, function (error) {
// 对请求错误做什么
console.log("error错误:", error)
return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 对响应数据前做什么
console.log("添加请求拦截器2:", response)
return response;
}, function (error) {
console.log("error错误2:", error)
// 响应错误后做什么
return Promise.reject(error);
});
}
在控制台中可以发现请求已发送,状态为404
1.2. axios函数封装
(1)在src目录下新建config文件夹,新建index.js,主要是让系统判断当前处于生产状态还是用户状态。
//src/api/index.js
export default{
baseUrl:{
dev:'/api/',//开发环境
pro:''//生产环境
}
}
(2)对axios函数进行二尺封装,方便后续使用。在根目录下新建api文件夹,新建axios.js文件。
//src/api/axios.js
import axios from 'axios'
import config from '../config'
// 将config和anios进行有机结合,对axios进行简单封装。
// 判断是不是生产环境,并拿到config中的dev环境,否则拿到config中的pro环境。
const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro
/**
* axios工具类,工具类拿到对应的url后,进行相应配置
*/
class HttpRequest {
constructor (baseUrl) {
this.baseUrl = baseUrl
}
/**
* 用于定义anios的相关配置的方法
* @returns {{header: {}, base: *}}
*/
getInsideConfig(){
const config = {
base:this.baseUrl,
header:{}
}
return config
}
/**
* 拦截器部分
* @param instance
*/
interceptors (instance) {
// 添加请求拦截器
instance.interceptors.request.use(function(config){
// 在发送前做什么
return config;
},function (error){
// 对请求错误做什么
return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function(response){
// 对响应数据前做什么
return response;
},function(error){
// 响应错误后做什么
return Promise.reject(error);
});
}
/**
* 接口请求
* @param options
* @returns {*}
*/
request(options){
//创建axios实例
const instance = axios.create()
// ES6语法解构,三点表示解构
options = {...this.getInsideConfig(), ...options}
// 调用拦截器
this.interceptors(instance)
return instance(options)
}
}
export default new HttpRequest(baseUrl)
1.3. 接口调用
(1)在src/api下新建data.js文件,用于添加网络接口
//src/api/data.js
// 这里引入的是文件,不是依赖
import axios from './axios'
/**
* 接口对外暴露
* @param param
* @returns {*}
*/
export const getMenu = (param) => {
return axios.request({
url:'/permission/getMenu',
method:'post',
data:param
})
}
(2)在src/views/home/index.vue中调用
//src/views/home/index.vue
mounted() {
// //接口请求一般在mounted下
// const axios = require('axios');
// // 上述请求也可以按以下方式完成(可选)
// axios.get('/user', {
// params: {
// ID: 12345
// }
// }).then(function (response) {
// console.log(response);
// })
// .catch(function (error) {
// console.log(error);
// })
// .finally(function () {
// // 总是会执行
// });
getMenu().then(res => {
console.log("post==",res)
})
}
//src/views/home/index.vue
<template>
<el-row class="home" :gutter="20" style="height:100vh;">
<!--用户布局-->
<el-col :span="9" class="user-section">
<el-card shadow="hover">
<div class="user-layout">
<img class="user-header" :src="userImg"/>
<div class="user-info-layout">
<p class="user-name">Admin</p>
<p class="user-nickname">超级管理员</p>
</div>
</div>
<div class="login-layout">
<p class="login-time">上次登录时间:<span>2024-12-12</span></p>
<p class="login-loc">上次登录地点:<span>济南</span></p>
</div>
</el-card>
<!--列表展示-->
<el-card class="list-section">
<el-table :data="tableData">
<el-table-column
v-for="(val,key) in tableLabel"
:key="key"
:prop="key"
:label="val">
</el-table-column>
</el-table>
</el-card>
</el-col>
<!--右侧布局-->
<el-col :span="15">
<!--订单统计-->
<el-col :span="8" v-for="(item) in countData"
:key="item.name" :offset="0">
<el-card class="order-section"
:body-style="{display:'flex', padding:0}">
<div class="order-layout">
<i class="order-icon" :class="'el-icon-'+item.icon"
:style="{background:item.color}"></i>
<div class="order-detail">
<p class="order-num">¥{{item.value}}</p>
<p class="order-title">{{item.name}}</p>
</div>
</div>
</el-card>
</el-col>
<el-card style="height:280px;">
</el-card>
<div class="graph">
<el-card style="height:260px;"></el-card>
<el-card style="height:260px;"></el-card>
</div>
</el-col>
</el-row>
</template>
<script>
import {getMenu} from '../../api/data.js'
export default {
name: "home",
data() {
return {
userImg: require("../../assets/images/user.png"),
tableData: [
{
name: "华为",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "荣耀",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "oppo",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "vivo",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "苹果",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "小米",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "三星",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
},
{
name: "魅族",
todayBuy: 100,
monthBuy: 300,
totalBuy: 800,
}
],
tableLabel: {
name: '课程',
todayBuy: '今日购买',
monthBuy: '本月购买',
totalBuy: '总购买',
},
countData: [
{
name: "今日支付订单",
value: 1234,
icon: "success",
color: "#2ec7c9",
offset: 0,
},
{
name: "今日收藏订单",
value: 210,
icon: "star-on",
color: "#ffb980",
offset: 1,
},
{
name: "今日未支付订单",
value: 1234,
icon: "s-goods",
color: "#5ab1ef",
offset: 2,
},
{
name: "本月支付订单",
value: 1234,
icon: "s-home",
color: "#fbcc00",
offset: 0,
},
{
name: "本月收藏订单",
value: 210,
icon: "s-cooperation",
color: "#ff4444",
offset: 1,
},
{
name: "本月未支付订单",
value: 1234,
icon: "s-shop",
color: "#33cc87",
offset: 2,
},
]
}
},
mounted() {
// //接口请求一般在mounted下
// const axios = require('axios');
// // 上述请求也可以按以下方式完成(可选)
// axios.get('/user', {
// params: {
// ID: 12345
// }
// }).then(function (response) {
// console.log(response);
// })
// .catch(function (error) {
// console.log(error);
// })
// .finally(function () {
// // 总是会执行
// });
getMenu().then(res => {
console.log("post==",res)
})
}
}
</script>
<style lang="less">
/*用户模块*/
.user-section {
margin: 10px 0
}
.user-layout {
display: flex;
flex-direction: row;
align-items: center;
border-bottom: #999 solid 1px;
padding: 0 10px 10px;
}
.user-header {
width: 100px;
height: 100px;
border-radius: 50%;
}
.user-info-layout {
display: flex;
flex-direction: column;
margin-left: 20px;
}
.user-name {
font-size: 18px;
color: black;
font-weight: 700;
}
.user-nickname {
font-size: 18px;
color: black;
margin-top: 5px;
font-weight: 700;
}
.login-layout {
display: flex;
flex-direction: column;
margin-left: 20px;
}
.login-time {
font-size: 17px;
color: black;
margin-top: 5px;
}
.login-loc {
font-size: 17px;
color: black;
margin-top: 8px;
}
/*列表展示*/
.list-section {
margin-top: 20px;
height: 460px;
}
/*订单统计*/
.order-section {
padding: 0 0;
margin: 10px 0 15px;
background-color: white;
}
.order-layout {
display: flex;
flex-direction: row;
align-items: center;
}
.order-icon {
display: flex;
width: 65px;
height: 65px;
//border-radius: 50%;
align-items: center;
justify-content: center;
}
.order-detail {
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 15px;
}
.order-num {
color: #333333;
font-size: 18px;
}
.order-title {
color: #333;
font-size: 18px;
font-weight: 700;
margin-top: 8px;
}
</style>
 axios网络请求示例下载
1.4. 对响应拦截器进行更改
对/src/api/index.js下的拦截器进行更改,打印拦截数据。
/**
* 拦截器部分
* @param instance
*/
interceptors(instance) {
// 添加请求拦截器
instance.interceptors.request.use(function (response) {
console.log("添加请求拦截器:", response)
// 在发送前做什么
return response;
}, function (error) {
// 对请求错误做什么
return Promise.reject(error);
});
// 添加响应拦截器
instance.interceptors.response.use(function (response) {
// 对响应数据前做什么
return response;
}, function (error) {
// 响应错误后做什么
return Promise.reject(error);
});
}
1.5. mockjs使用
官方文档
mock可以拦截ajax请求,在mock的回调函数中返回接口的响应数据。可以模拟后端发送过来的接口数据。mock可以使用数据模板生成数据。
在api下新建mock.js,先npm i mockjs。Mock.mock(url,回调函数),这里模块化编程,提前准备好数据模板,在api下新建mockServeData文件夹,新建home.js文件,存放home页面下的mock的模拟数据。
//src/api/mock.js
import Mock from 'mockjs'
import homeApi from './mockServeData/home.js'
Mock.mock('/home/getData',homeApi.getStatisticalData)
//src/api/mockServeData/home.js
// mock数据模拟
import Mock from 'mockjs'
// 图表数据
let List = []
export default {
getStatisticalData: () => {
//Mock.Random.float 产生随机数100到8000之间 保留小数 最小0位 最大0位
for (let i = 0; i < 7; i++) {
List.push(
Mock.mock({
苹果: Mock.Random.float(100, 8000, 0, 0),
vivo: Mock.Random.float(100, 8000, 0, 0),
oppo: Mock.Random.float(100, 8000, 0, 0),
魅族: Mock.Random.float(100, 8000, 0, 0),
三星: Mock.Random.float(100, 8000, 0, 0),
小米: Mock.Random.float(100, 8000, 0, 0)
})
)
}
return {
code: 20000,
data: {
// 饼图
videoData: [
{
name: '小米',
value: 2999
},
{
name: '苹果',
value: 5999
},
{
name: 'vivo',
value: 1500
},
{
name: 'oppo',
value: 1999
},
{
name: '魅族',
value: 2200
},
{
name: '三星',
value: 4500
}
],
// 柱状图
userData: [
{
date: '周一',
new: 5,
active: 200
},
{
date: '周二',
new: 10,
active: 500
},
{
date: '周三',
new: 12,
active: 550
},
{
date: '周四',
new: 60,
active: 800
},
{
date: '周五',
new: 65,
active: 550
},
{
date: '周六',
new: 53,
active: 770
},
{
date: '周日',
new: 33,
active: 170
}
],
// 折线图
orderData: {
date: ['20191001', '20191002', '20191003', '20191004', '20191005', '20191006', '20191007'],
data: List
},
tableData: [
{
name: 'oppo',
todayBuy: 500,
monthBuy: 3500,
totalBuy: 22000
},
{
name: 'vivo',
todayBuy: 300,
monthBuy: 2200,
totalBuy: 24000
},
{
name: '苹果',
todayBuy: 800,
monthBuy: 4500,
totalBuy: 65000
},
{
name: '小米',
todayBuy: 1200,
monthBuy: 6500,
totalBuy: 45000
},
{
name: '三星',
todayBuy: 300,
monthBuy: 2000,
totalBuy: 34000
},
{
name: '魅族',
todayBuy: 350,
monthBuy: 3000,
totalBuy: 22000
}
]
}
}
}
}
在main.js中引入import ‘./api/mock.js’。
在src/views/home下index.vue中引入getData。import { getData } from ‘…/…/api/data.js’,并暴露使用。
//src/views/home/index.js
mounted(){
getData().then(res => {
console.log(res)
})
}
在api中data.js中编写getData,这里没有写请求类型,默认是get请求。
//data.js
export const getData = () =>{
return axios.request({
url:'/home/getData'
})
}
url为:
接口拦截成功,并返回数据。
将数据进行解构
对home的index.vue的mounted进行修改,并将return中的tableData定义为空数组,tableData:[]。
mounted(){
getData().then(res => {
const { code,data } = res.data
if (code === 20000){
this.tableData = data.tableData
}
console.log(res)
})
}
前后数据区别:一个是原本写死的数据,一个是模拟后端的mock数据。
VueWeb Mock示例下载