项目演示
https://www.bilibili.com/video/BV1dY411T71E?t=31.3
vue + element-ui 项目演示
四、项目实战四
Ⅰ、axios 的使用和二次封装
1. axios 的基本使用
- Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
- 特性:
从浏览器中创建 XMLHttpRequests
从 node.js 创建 http 请求
支持 Promise API
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换 JSON 数据
客户端支持防御 XSRF - 安装 axios
npm i axios
- main.js 文件中引入 axios
import http from "axios";
- 使用 axios,因为 axios 不是一个插件,所以要全局使用,只能将它绑定在 Vue 的 prototype 属性上
Vue.prototype.$http = http;
- axios 执行 get 请求案例
// 为给定 ID 的 user 创建请求 axios.get('/user?ID=12345') .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
// 上面的请求也可以这样做 axios.get('/user', { params: { ID: 12345 } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
- axios 执行 post 请求
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
2. axios 的二次封装
为什么进行二次封装?
api 可以统一管理,不管接口有多少,所有的接口都可以非常清晰,容易维护。
- 创建 config 文件夹,并在该文件夹下创建 index.js 文件
// 项目的配置文件 // 配置baseUrl,之后就可以传相对路径 export default { baseUrl: { dev: '/api/', //开发环境 pro: '', //生产环境 } };
- 创建 api 文件夹,在该文件夹下创建 axios.js 文件
// 二次封装 将 axios 和 配置文件 进行结合 import axios from 'axios' // 引入对路径的基本配置,便可以使用相对路径 import config from '../config/index' // 设置配置,因为开发环境(dev)、测试环境(test)和生产环境(prod)的baseUrl地址不一样 // process.env 包含着有关系统环境的信息 // NODE_ENV:判断生成环境或开发环境还是测试环境的依据。 const baseUrl = process.env.NODE_ENV === 'development' ? config.baseUrl.dev : config.baseUrl.pro class HttpRequst { constructor(baseUrl) { // 将baseUrl 添加到当前实例的baseUrl属性上 this.baseUrl = baseUrl } // 定义 axios相关的配置 getInsideConfig() { const config = { // 拿到当前实例下的 baseUrl baseURL: this.baseUrl, // 请求头的信息 header: {} } return config } // 拦截器:在请求或响应被then或catch处理前拦截它们 interceptors(instance) { // 添加请求拦截器 instance.interceptors.request.use(function (config) { // 在发送请求之前做些什么 console.log('拦截处理请求'); return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); // 添加响应拦截器 instance.interceptors.response.use(function (response) { console.log('处理相应'); // 对响应数据做点什么 return response.data; }, function (error) { console.log(error); // 对响应错误做点什么 return Promise.reject(error); }); } // 接口请求时调用 request (options) { // 创建 axios实例 const instanse = axios.create() // 对相关的配置信息getInsideConfig()进行解构, 对传入的相关参数options解构 options = { ...(this.getInsideConfig()), ...options } // console.log(options); this.interceptors(instanse) // 返回接口请求的结果 return instanse(options) } } // 暴露传入baseUrl的实例 export default new HttpRequst(baseUrl)
- 在 api 文件夹中创建 data.js 文件,该文件写入接口请求
// 写入接口请求的文件 import axios from './axios' export const getMenu = (param) => { return axios.request({ url: '/permission/getMenu', //接口的相关地址 method: 'post', //请求方式 data: param //传入的参数 }) }
- 在 ./home/index.vue 中导入 getMenu
import { getMenu } from "../../api/data.js";
- 在 ./home/index.vue 的 mounted 函数中使用,之后刷新控制台,会发现发出了请求,但有 404 错误(因为并没有获取到后台数据)
getMenu.then((res) => { console.log(res) })
Ⅱ、mock 数据模拟
1. mock 简单介绍
mock 可以干什么 ?
————————————————
答:生成随机数据,拦截 Ajax 请求
2. mock 的基本使用
- 基本语法解释:
(1)rurl:url 的规则(指定的url或者正则)
(2)rtype:接口请求的类型(get、post)
(3)template | function(options) 返回的数据 用模板或者回调函数
Mock.mock(rurl?, rtype?, template|function(options))
- 安装 mockjs
npm i mockjs
- 在 api 文件夹下创建 mockServerData 文件夹,在该文件夹下创建 home.js 文件,进行对 home 主页(列表、折线图、柱状图和饼状图)相关数据的模拟
import Mock from 'mockjs' export default { getStatisticalData: () => { //Mock.Random.float 产生随机数100到8000之间 保留小数 最小0位 最大0位 //用于折线图的随机数据模拟(现在还用不到) for (let i = 0; i < 8; 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, //状态码(20000表示正常的数据) data: { 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 } ] } } } }
- 在 api 文件夹下 创建 mock.js 文件,用于对使用到 mock 的文件进行导入和使用
import Mock from 'mockjs' import homeApi from './mockServerData/home' Mock.mock('/api/home/getData', homeApi.getStatisticalData)
- 在 main.js 中进行 mock 的引入
import "../api/mock.js";
- 把 ./home/index.vue 中 的 getMenu 换成 getMenu
import { getMenu } from "../../api/data.js";
- 在 data.js 文件中定义 getData
// 写入接口请求的文件 import axios from './axios' export const getData = () => { return axios.request ({ url: '/home/getData', //接口的相关地址 method: 'get' //请求方式 }) }
- 在 ./home/index.vue 中,把 tableData中的数据置空,因为把这部分数据已经转移到了 home.js 中的 tableData 中存储
data() { return { tableData: [] } }, mounted() { // 将res下的code和data解构 data是数组List中的数据 const { code, data } = res; // 正常接口返回的时候 if (code === 20000) { //获取home.js中定义好的tableData数据 this.tableData = data.tableData; } }
不积跬步无以至千里 不积小流无以成江海