1. 安装
npm i mockjs vite-plugin-mock 安装 mockjs和 vite-plugin-mock插件
2. vite.config.ts中集成插件
javascript
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'//引入按需引入vant插件
import { VantResolver } from 'unplugin-vue-components/resolvers'
import { viteMockServe } from 'vite-plugin-mock'//引入mock插件
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [VantResolver()],
}),
viteMockServe({//配置mock插件
// 更多配置见最下方
supportTs: true,
logger: false,
mockPath: './mock/', // 文件位置
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
3. mock文件夹mock接口数据
scr同级创建mock文件夹→account.ts(模块拆分,post请求config.body取参)
arduino
const accountList = []
/**
* 用户注册
*/
export const mockRegister = {
url:'/mock/account/register',
method:'post',
response:(config)=>{
// 注册业务逻辑
// 1. 获取用户名和密码
const {username,password,headerimg} = config.body
// 2. 保存用户信息
// localStorage.setItem('USER',JSON.stringify({username,password,headerimg}))
const user = {username,password,headerimg}
accountList.push(user)
// 3. 响应内容
return {
resultCode:1,
resultInfo:'注册成功'
}
}
}
/**
* 用户登录
*/
export const mockLogin = {
url:'/mock/account/login',
method:'post',
response:(config)=>{
// 登录业务逻辑
// 1. 获取用户名和密码
const {username,password,headerimg} = config.body
// 2. 判断用户是否注册
// let userstr = localStorage.getItem('USER')
// let user = userstr? JSON.parse(userstr):''
const user = accountList.find(item=>item.username==username && item.password==password)
if(user){
return {
resultCode:1,
resultInfo: {
username,
password,
headerimg
}
}
}else{
return {
resultCode:-1,
resultInof:'账户出错'
}
}
}
}
scr同级创建mock文件夹→good.ts(模块拆分,get请求config.query取参)
typescript
import { goodsListData, bannerListData } from './data/goodsData'
/**
* 商品列表
*/
export const goodsList = {
url: '/mock/goods/list',
method: 'get',
response: (config:any) => {
//get请求参数
let { pageNo, pageSize } = config.query
pageNo = pageNo || 1
pageSize = pageSize || 10
console.log('pageNo ', pageNo, ' pageSize :', pageSize)
// 分页
const startIndex = (pageNo - 1) * pageSize
const endIndex = pageNo * pageSize
const list = goodsListData.slice(startIndex, endIndex)
if(list.length>0){
return {
resultCode: 1,
resultInfo: {
list,
},
}
}else{
return {
resultCode:-1,
resultInfo:'没有数据'
}
}
},
}
/**
* banner轮播
*/
export const bannerList = {
url: '/mock/banner',
method: 'get',
response: () => {
return {
resultCode: 1,
resultInfo: {
list: bannerListData,
},
}
},
}
scr同级创建mock文件夹→data文件夹→goodsData.ts(模块拆分,存放数据)
javascript
export const goodsListData = [
{
id: 49,
shop: '【苏宁生鲜】鲜美来东海带鱼600g 海鲜水产 鲜活冷冻',
picture:
'https://image1.suning.cn/uimg/b2c/newcatentries/0010128947-000000000614428161_1_800x800.jpg',
product: '【苏宁生鲜】鲜美来东海带鱼600g 海鲜水产 鲜活冷冻',
price: 18.88,
oldprice: 69,
putaway: 1,
detail: null,
categoryname: '川湘菜',
categoryId: 3,
},
{
id: 48,
shop: '【苏宁生鲜】恒都巴西牛腩块1kg 进口牛肉 精选肉类',
picture:
'https://image1.suning.cn/uimg/b2c/newcatentries/0010128947-000000000614167327_1_800x800.jpg',
product: '【苏宁生鲜】恒都巴西牛腩块1kg 进口牛肉 精选肉类',
price: 18.98,
oldprice: 49,
putaway: 1,
detail: null,
categoryname: '川湘菜',
categoryId: 3,
},
{
id: 45,
shop: '贝克巴斯(BECBAS)E50 厨房家用食物垃圾处理器 厨余垃圾粉碎机 无线开关免打孔',
picture:
'https://image3.suning.cn/uimg/b2c/newcatentries/0000000000-000000000616963357_2_800x800.jpg',
product:
'贝克巴斯(BECBAS)E50 厨房家用食物垃圾处理器 厨余垃圾粉碎机 无线开关免打孔',
price: 38,
oldprice: 67,
putaway: 1,
detail: null,
categoryname: '大家电',
categoryId: 9,
},
{
id: 44,
shop: '科龙(Kelon) 正1.5匹 定速 冷暖 空调挂机 ',
picture:
'https://image4.suning.cn/uimg/b2c/newcatentries/0000000000-000000000178605073_1_800x800.jpg',
product: '科龙(Kelon) 正1.5匹 定速 冷暖 空调挂机 ',
price: 156.9,
oldprice: 190,
putaway: 1,
detail: '这个商品不错',
categoryname: '排骨',
categoryId: 7,
},
{
id: 42,
shop: '华帝浴室花洒 增压花洒 主体全铜花洒 沐浴莲蓬头【自营】H-CS0014-B1D.W',
picture:
'https://image2.suning.cn/uimg/b2c/newcatentries/0000000000-000000000604135232_1_800x800.jpg',
product:
'华帝浴室花洒 增压花洒 主体全铜花洒 沐浴莲蓬头【自营】H-CS0014-B1D.W',
price: 18.87,
oldprice: 90,
putaway: 1,
detail: null,
categoryname: '排骨',
categoryId: 7,
},
{
id: 41,
shop: '长虹(CHANGHONG) 大1匹 冷暖定频 快速制冷热 空调挂机 KFR-26GW/DHID(W1-J)+2',
picture:
'https://image2.suning.cn/uimg/b2c/newcatentries/0000000000-000000000126066901_1_800x800.jpg',
product:
'长虹(CHANGHONG) 大1匹 冷暖定频 快速制冷热 空调挂机 KFR-26GW/DHID(W1-J)+2',
price: 18.48,
oldprice: 35,
putaway: 1,
detail: null,
categoryname: '火锅',
categoryId: 8,
},
{
id: 40,
shop: '小米智米(SMARTMI)智能马桶盖 家用全自动冲洗即热式加热外置过滤器杀菌洁便器',
picture:
'https://image4.suning.cn/uimg/b2c/newcatentries/0000000000-000000000673521926_1_800x800.jpg',
product:
'小米智米(SMARTMI)智能马桶盖 家用全自动冲洗即热式加热外置过滤器杀菌洁便器',
price: 34.98,
oldprice: 47,
putaway: 1,
detail: null,
categoryname: '火锅',
categoryId: 8,
},
]
/**
* 轮播数据
*/
export const bannerListData = [
{
id: 1,
url: 'https://img.alicdn.com/imgextra/i3/2053469401/O1CN01g8ituT2JJiCsKjmDz_!!2053469401.png',
content: '商家1',
number: 1,
},
{
id: 11,
url: 'https://img2.baidu.com/it/u=717979571,3244631707&fm=253&fmt=auto&app=138&f=JPEG?w=1280&h=400',
content: '舒适度满分',
number: 1,
},
{
id: 12,
url: 'https://img1.baidu.com/it/u=1733684228,4177721799&fm=253&fmt=auto&app=138&f=JPEG?w=1200&h=500',
content: '曲线在召唤',
number: 1,
},
]
scr同级创建创建mock文件夹→index.ts(模块集成暴露)
javascript
import { bannerList, goodsList } from './goods'
import { mockRegister, mockLogin } from './account'
const goods = [bannerList, goodsList] // 商品模块接口
const account = [mockLogin, mockRegister] // 个人中心接口
export default [...goods,...account]
4. utils文件夹→requestMock.ts(封装axios,不封装直接使用axios也行)
javascript
import axios from 'axios'
import { Toast } from 'vant'
export let baseURL = 'http://10.7.163.159:5173'
/**
* 创建axios实例
* 封装baseURL
*/
const axiosInstance = axios.create({
baseURL, // 服务根地址
timeout: 3000, // 超时时间
})
/**
* 请求拦截器
*/
axiosInstance.interceptors.request.use(
config => {
const token = localStorage.getItem('TOKEN')
if (token) {
config.headers['Authorization'] = token
}
return config
},
error => {
return Promise.reject(error)
}
)
/**
* 响应拦截器
*/
axiosInstance.interceptors.response.use(
response => {
return response.data
},
error => {
const { response } = error
if (response) {
const status = response.status
switch (status) {
case 404:
Toast('资源不存在 404')
break
case 401:
Toast('Unauthorized 身份验证凭证缺失!')
break
case 403:
Toast('403 Forbidden - 拒绝访问!')
break
case 500:
Toast('服务器出错')
break
default:
Toast('出现异想不到的错误!')
break
}
} else {
// 说明服务器连结果都没有返回,可能的原因有两种:
/**
* 1. 服务器崩掉了
* 2. 前端客户端断网状态
*/
if (!window.navigator.onLine) {
// 判断为断网,可以跳转到断网页面
Toast('网络不可用,请检查您的网络连接!')
return
} else {
Toast('连接服务端出错!' + error?.message)
return Promise.reject(error)
}
}
return Promise.reject(error)
}
)
export default axiosInstance
5. api文件夹→index.ts文件中定义接口
php
import axiosInstance from '@/utils/request'
import axiosMockInstance from '@/utils/requestMock'
import type{IResponse} from '@/types/types'
/**
* 产品列表
* shopKey: 店铺名称
* productKey: 产品名称
* @returns
*/
export const RequestShopList = (pageNo:number,pageSize:number):Promise<IResponse>=>{
return axiosInstance({
method:'get',
url:'/api/shop',
params:{
pageSize,
pageNo,
}
})
}
/**
* 轮播
*/
export const RequestBanner = ():Promise<IResponse>=>{
return axiosInstance({
method:'get',
url:'/api/banner'
})
}
/**
* 登录
*/
export const RequestLogin = (username:string,password:string):Promise<IResponse>=>{
return axiosMockInstance({
method:'post',
// url:'/api/member/login',
url:'/mock/account/login',
data:{
username,
password
}
})
}
/**
* 注册
*/
export const RequestRegister = (username:string,password:string,headerimg:string):Promise<IResponse>=>{
return axiosMockInstance({
method:'post',
url:'/mock/account/register',
data:{
username,
password,
headerimg
}
})
}