vue3之vite配置vite-plugin-mock使用mock轻松创建模拟数据提高开发效率

简介: vue3之vite配置vite-plugin-mock使用mock轻松创建模拟数据提高开发效率

什么是Mock数据

Mock 可以翻译为“模拟”,在前端开发中通常指模拟后端接口和数据。


在软件开发过程中,Mock数据指的是一种虚拟的测试数据,用于模拟真实的数据情况。它可以用来替代真实的数据源,从而实现在没有真实数据的情况下进行开发和测试的需求。


我们在开发的时候,一般都是前后端同时开发,尤其是某些后台系统开发时,很多前端同学分分钟就可以做完静态页面的开发,然后就是摸鱼时间,等待后端的接口。如果你的后端同事非常配合,愿意在设计数据库的时候顺便定好返回的数据结构和字段,并且联调时间很紧张的时候,这时候你应该考虑着手去做一下前端 mock,为联调争取时间。


Mock数据的使用不仅可以提高开发效率,还可以避免与真实数据源的依赖性,减少开发过程中的等待时间,以及降低测试环境的复杂性。

使用Mock数据的优点

简单性:不需要复杂的配置和部署过程,可以快速地创建和管理模拟数据。

灵活性:可以满足不同的开发需求,例如支持不同的请求类型、不同的请求方式等。

真实性:能够生成更接近真实的数据,可以模拟不同的数据类型、格式和结构。

维护性:可以方便地更新和修改模拟数据。

合作性: 可以在团队内方便的共享模拟数据。


Mock数据使用步骤

一、安装依赖mockjs、vite-plugin-mock

提供本地和生产模拟服务。

vite 的数据模拟插件,是基于 vite.js 开发的。 并同时支持本地环境和生产环境。 Connect 服务中间件在本地使用,mockjs 在生产环境中使用。

npm i mockjs vite-plugin-mock --save-dev


二、vite.config.ts 文件中配置

// vite.config.ts
import { defineConfig } from 'vite'
import { viteMockServe } from 'vite-plugin-mock'
import vue from '@vitejs/plugin-vue'

export default defineConfig(({ command }) => {
  return {
    plugins: [
      vue(),
      viteMockServe({
        mockPath: 'mock', // mock文件夹路径
        enable: command === 'serve' // 只有开发环境才开启mock
      }),
    ],
  }
})
  • viteMockServe 配置
{
    mockPath?: string;
    ignore?: RegExp | ((fileName: string) => boolean);
    watchFiles?: boolean;
    enable?: boolean;
    ignoreFiles?: string[];
    configPath?: string;
    logger?:boolean;
}
参数 类型 默认值 说明
mockPath string mock 设置模拟.ts 文件的存储文件夹
ignore RegExp undefined 自动读取模拟.ts 文件时,请忽略指定格式的文件
watchFiles boolean true 设置是否监视mockPath对应的文件夹内文件中的更改
enable boolean true 是否启用 mock 功能
configPath string vite.mock.config.ts 设置模拟读取的数据条目
logger boolean true 是否在控制台显示请求日志


三、在根目录下创建mock文件

项目文件夹下新建mock文件夹,用于存放本地mock文件

// mock/user.ts

const createUserList = () => {
    return [
        {
            userId: 1,
            avatar: 'https://pic1.zhimg.com/80/v2-083faf550543c1e9f134b56b3322ee3c_720w.webp',
            username: 'admin',
            password: '123456789',
            desc: '下船不谈船里事',
            roles: ['平台管理员'],
            buttons: ['cuser.detail'],
            routes: ['home'],
            token: 'Admin Token'
        },
        {
            userId: 2,
            avatar: 'https://pic1.zhimg.com/80/v2-e1427f6a21122ac163ff98d24f55d372_720w.webp',
            username: 'system',
            password: '123456789',
            desc: '旧人不谈近况,新人不讲过往',
            roles: ['系统管理员'],
            buttons: ['cuser.detail', 'cuser.user'],
            routes: ['home'],
            token: 'Admin Token'
        }
    ]
}
export default [
    // 用户登录接口
    {
        url: '/api/user/login',
        method: 'post',
        response: ({ body }: any) => {
            // 获取请求体携带过来的用户名与密码
            const { username, password } = body
            // 调用获取用户信息函数,用于判断是否有此用户
            const checkUser = createUserList().find(
                (item) => item.username === username && item.password === password
            )
            // 没有用户则返回失败信息
            if (!checkUser) {
                return {
                    code: 201,
                    data: {
                        message: '账号或者密码不正确'
                    }
                }
            }
            // 如果有返回成功信息
            const { token } = checkUser
            return {
                code: 200,
                data: {
                    token
                }
            }
        }
    },
    // 获取用户信息接口
    {
        url: '/api/user/info',
        method: 'get',
        response: (request: any) => {
            // 获取请求头携带的 token
            const token = request.headers.token
            // 查看用户信息数据中是否包含有此 token 的用户
            const checkUser = createUserList().find((item) => item.token === token)
            // 没有就返回失败信息
            if (!checkUser) {
                return {
                    code: 201,
                    data: {
                        message: '获取用户信息失败'
                    }
                }
            }
            // 有就返回成功信息
            return {
                code: 200,
                data: {
                    checkUser
                }
            }
        }
    }
]


四、编写api接口调用文件

1、src文件夹下新建utils/request.ts
// utils/request.ts

import axios from "axios";

//创建一个axios实例
const request = axios.create({
    baseURL: '',
    timeout: 20000,
});


// 添加请求拦截器
request.interceptors.request.use(
    function (config) {
        // 请求地址携带时间戳
        const _t = new Date().getTime()
        config.url += `?${_t}`
        
        // 请求头携带token
        config.headers['token'] = localStorage.getItem('token') || ''

        // 在发送请求之前做些什么
        // console.log('我要准备请求啦------')
        // console.log(config, '请求配置')
        
        return config;
    },
    function (error) {
        // 对请求错误做些什么
        return Promise.reject(error);
    }
);

// 添加响应拦截器
request.interceptors.response.use(
    function (response) {
        // 对响应数据做点什么
        // console.log('我接收到响应数据啦------')
        // console.log(response, '响应配置')
        if (response.status === 200) {
            return Promise.resolve(response.data)
        } else {
            return Promise.reject(response)
        }
    },
    function (error) {
        // 对响应错误做点什么
        if (error && error.response) {
            switch (error.response.status) {
                case 400:
                    error.message = '错误请求';
                    break;
                case 401:
                    error.message = '未授权,请重新登录';
                    break;
                case 403:
                    error.message = '拒绝访问';
                    break;
                case 404:
                    error.message = '请求错误,未找到该资源';
                    break;
                case 405:
                    error.message = '请求方法未允许';
                    break;
                case 408:
                    error.message = '请求超时';
                    break;
                case 500:
                    error.message = '服务器端出错';
                    break;
                case 501:
                    error.message = '网络未实现';
                    break;
                case 502:
                    error.message = '网络错误';
                    break;
                case 503:
                    error.message = '服务不可用';
                    break;
                case 504:
                    error.message = '网络超时';
                    break;
                case 505:
                    error.message = 'http版本不支持该请求';
                    break;
                default:
                    error.message = `未知错误${error.response.status}`;
            }
        } else {
            error.message = "连接到服务器失败";
        }
        return Promise.reject(error);
    }
);


/*
 *  get请求:从服务器端获取数据
 *  url:请求地址
 *  params:参数
 * */
export function get(url:string, params = {}) {
    return new Promise((resolve, reject) => {
        request({
            url: url,
            method: 'get',
            params: params
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}

/*
 *  post请求:向服务器端提交数据
 *  url:请求地址
 *  params:参数
 * */
export function post(url:string, params = {}) {
    return new Promise((resolve, reject) => {
        request({
            url: url,
            method: 'post',
            data: params
        }).then(response => {
            resolve(response);
        }).catch(error => {
            reject(error);
        });
    });
}

// 对外暴露请求方法
export default {
    get,
    post
}
2、src文件夹下新建api/user.ts
// api/user.ts

import { get, post } from './request';

const api = {
    login: '/api/user/login',
    users: '/api/user/info'
}

//登录
export const login = (params: any) => {
    return post(api.login, params).then((res: any) => {
        if (res.code === 200) {
            localStorage.setItem('token', res.data.token);
        }
        return Promise.resolve(res);
    })
}


//获取用户信息
export const getUserInfo = () => {
    const token = localStorage.getItem('token');
    if (!token) return Promise.reject(new Error('用户未登录'));
    return get(api.users);
}


五、业务页面调用

// App.vue

import { onBeforeMount } from 'vue'
import {login,getUserInfo} from "./utils/user"

onBeforeMount(async () => {
  // 登录
  const user = await login({
    username: 'admin',
    password: '123456789'
  })
  console.log(user)
  
  // 获取用户信息
  const users = await getUserInfo()
  console.log(users)
})
//// App.vue

import { onBeforeMount } from 'vue'
import {login,getUserInfo} from "./utils/user"

onBeforeMount(async () => {
  // 登录
  const user = await login({
    username: 'admin',
    password: '123456789'
  })
  console.log(user)
  
  // 获取用户信息
  const users = await getUserInfo()
  console.log(users)
})

六、Mock的用法规则

import mockJS from 'mockjs'

const userList = mockJS.mock({
    // 属性 list 的值是一个数组,其中含有 1 到 10 个元素
    'list|1-10': [
        {
            // 随机生成id号
            id: '@id',
            // 随机生成中文姓名
            name: '@cname',
            // 属性 id 是一个自增数,起始值为 1,每次增 1
            'id|+1': 1,
            // 随机生成ip地址
            ip: '@ip',
            // 随机生成省市区地址
            address:'@county(true)',
            // 随机生成邮政编码
            zip:'@zip',
            // 随机生成18-70之间的年龄
            "age|18-70": 20,
            // 随机生成日期
            date: '@date("yyyy-MM-dd")',
            // 随机生成头像
            avatar:"@image('200x200')",
        }
    ]
})

七、在生产环境中的使用

1、创建mockProdServer.ts 文件
//  mockProdServer.ts

import { createProdMockServer } from 'vite-plugin-mock/client'

// 逐一导入您的mock.ts文件
// 如果使用vite.mock.config.ts,只需直接导入文件
// 可以使用 import.meta.glob功能来进行全部导入
import testModule from '../mock/test'

export function setupProdMockServer() {
  createProdMockServer([...testModule])
}
2、配置 vite-plugin-mock
import { viteMockServe } from 'vite-plugin-mock'

import { UserConfigExport, ConfigEnv } from 'vite'

export default ({ command }: ConfigEnv): UserConfigExport => {
  return {
    plugins: [
      viteMockServe({
        mockPath: 'mock',
        // 根据项目配置。可以配置在.env文件
        enable: true,
      }),
    ],
  }
}
3、注意事项
  • 无法在 mock.ts 文件中使用 node 模块,否则生产环境将失败
  • 模拟数据如果用于生产环境,仅适用于某些测试环境。 不要在正式环境中打开它,以避免不必要的错误。 同时,在生产环境中,它可能会影响正常的 Ajax 请求,例如文件上传/下载失败等。
目录
相关文章
|
6月前
|
JavaScript 前端开发 安全
Vue 3
Vue 3以组合式API、Proxy响应式系统和全面TypeScript支持,重构前端开发范式。性能优化与生态协同并进,兼顾易用性与工程化,引领Web开发迈向高效、可维护的新纪元。(238字)
911 139
|
6月前
|
缓存 JavaScript 算法
Vue 3性能优化
Vue 3 通过 Proxy 和编译优化提升性能,但仍需遵循最佳实践。合理使用 v-if、key、computed,避免深度监听,利用懒加载与虚拟列表,结合打包优化,方可充分发挥其性能优势。(239字)
504 1
|
7月前
|
开发工具 iOS开发 MacOS
基于Vite7.1+Vue3+Pinia3+ArcoDesign网页版webos后台模板
最新版研发vite7+vue3.5+pinia3+arco-design仿macos/windows风格网页版OS系统Vite-Vue3-WebOS。
811 11
|
6月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
569 0
|
8月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
869 1
|
8月前
|
缓存 JavaScript UED
除了循环引用,Vue3还有哪些常见的性能优化技巧?
除了循环引用,Vue3还有哪些常见的性能优化技巧?
461 0
|
9月前
|
JavaScript
vue3循环引用自已实现
当渲染大量数据列表时,使用虚拟列表只渲染可视区域的内容,显著减少 DOM 节点数量。
213 0
|
JavaScript
|
7月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
648 2
|
6月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
546 137

热门文章

最新文章

下一篇
开通oss服务