简介:这份 Vue3 练手工程面向刚接触 Vue3 新语法、希望快速理解 Element-Plus 与 Mockjs 接入方式的开发者,也适合需要现成脚手架直接扩展业务页面的前端学习者。工程已配置好 Vite、axios、Mockjs 与 ESLint,并基于 Element-Plus 的 Table 组件完成了一个可直接运行的表格示例,能帮助读者把注意力放在组件使用、接口模拟和页面搭建上,而不是反复处理环境初始化。压缩包共 27 个文件,约 130KB,以 9 个 vue 组件、3 个 json 配置、3 个 js 脚本、3 份 md 说明以及 css、图片和入口 html 等为主,体量轻巧却覆盖了工程启动所需的核心结构。已有 2140 人学习,说明其作为入门参照具有一定参考价值。读者可从中查看 Vue3 组合式写法的实际组织方式、Mockjs 假数据与 axios 请求的配合、Element-Plus 表格页面的引入路径,并借助 README 与注释梳理目录职责,在此基础上替换数据、增加路由或复制页面模块,较快搭起自己的练习项目。
1. 先别急着 npm install:Vue3 + Element-Plus + mockjs 的环境门槛
拿到标注「环境已经配好」的 vue3-demo,很多人第一反应是解压后直接 npm install,结果页面白屏、Element-Plus 组件解析不到、mockjs 请求 404。Vue3 框架配 Element-Plus 和 Mockjs 假数据这套组合在后台演示、内部工具里太常见,坑却集中在 Node 大版本、依赖锁和 mock 开关三处。装不好不是代码问题,是环境没对齐。适合想快速跑通演示工程、又不想从脚手架重建的开发者。
2. 从 vue3-demo 到 npm run dev:Node、依赖锁与启动脚本一次对齐
2.1 先查 Node 与 npm:版本不对,后面全是玄学
拿到工程后不要先改代码,先在终端确认当前 Node 和 npm 是哪一套。Vue3 工程本身对 Node 的要求通常写在 package.json 的 engines 字段里,没写就看锁文件生成时的提示和构建工具要求。Node 大版本跨太多,常见表现是安装依赖时报语法错误、启动时提示 API 不存在,或者 Vite 直接起不来。我的习惯是先看版本,再看 npm 源,最后才碰依赖。
# 查看当前 Node 与 npm 版本 node -v npm -v # 查看 npm 源,避免安装时卡在拉包阶段 npm config get registry # 如果工程根目录有 .nvmrc 或 .node-version,优先按文件切换 cat .nvmrc 2>/dev/null || cat .node-version 2>/dev/null这几条命令不产生副作用,作用是把「本机环境」和「工程预期环境」摆到同一张桌面上。node -v看大版本是否和工程匹配;npm config get registry看源是否可达;.nvmrc或.node-version是工程作者留下的版本线索,有就按它切,没有就以 package.json 的 engines 为准。不要一边报错一边反复删 node_modules,那通常解决不了版本错位。
| 检查项 | 常见情况 | 处理方式 |
|---|---|---|
| package.json 有 engines | 写明了 Node 范围 | 按范围切换 Node 大版本 |
| package.json 无 engines | 工程没约束 | 用当前 LTS,别用过旧版本 |
| 有 package-lock.json | 依赖版本已锁定 | 优先npm ci |
| 无锁文件 | 版本可能漂移 | npm install后提交锁文件 |
| npm 源不可达 | 安装卡住或超时 | 切到可用源再重试 |
提示:Node 版本不是越新越好。工程里如果用了某个构建工具的老插件,新 Node 大版本反而会让安装阶段报错。先对齐,再谈优化。
2.2 打开 vue3-demo 先看 package.json:脚本、依赖与锁文件
解压或拷贝 vue3-demo 后,先别急着安装。打开 package.json 看三处:scripts 里的 dev/build/preview 分别调用了什么,dependencies 和 devDependencies 里有没有 Element-Plus、mockjs,以及有没有 package-lock.json。Vue3 项目常见的是 Vite 脚本,但也不排除工程使用其他构建工具,所以命令要以 scripts 为准,不要凭习惯硬敲。
{ "scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" }, "dependencies": { "vue": "^3.x", "element-plus": "^2.x" }, "devDependencies": { "mockjs": "^1.x", "vite": "^5.x" } }上面是结构示意,不是让你照抄版本号。重点看三件事:dev脚本决定启动命令;element-plus放在 dependencies 还是 devDependencies 会影响生产安装;mockjs通常只用于开发联调,放 devDependencies 更合适。锁文件存在时,npm ci会严格按锁文件安装,适合复现环境;锁文件缺失或刚改过依赖,才用npm install生成新锁。
# 有锁文件时优先走 ci,安装结果更可控 npm ci # 没有锁文件,或刚调整过依赖时使用 install npm install # 安装完成后检查顶层依赖是否齐全 npm ls vue element-plus mockjs --depth=0npm ci会先删除 node_modules 再按锁文件安装,速度快、结果稳定,但要求锁文件和 package.json 一致;不一致时会直接报错,这反而是好事,能提前暴露依赖变更。npm install更宽松,会尝试解析版本范围并更新锁文件。npm ls用来确认三个核心包是否真的落在顶层依赖里,避免出现「装了但没装到项目里」的情况。
2.3 安装依赖并启动:npm run dev 背后的端口与环境变量
依赖装完后启动 dev 脚本。Vite 项目默认会开一个本地端口,端口被占用时会自动顺延,但团队协作或需要固定地址时,最好显式传参。启动命令不要只写npm run dev就完事,先看终端输出的 Local 地址,再用浏览器打开。如果工程里配了环境变量文件,启动前也要确认.env.development是否存在。
# 常规启动 npm run dev # 需要局域网访问或固定端口时,向脚本传参 npm run dev -- --host 0.0.0.0 --port 5173 # 构建生产包,提前暴露编译问题 npm run build--host 0.0.0.0用于让同网段设备访问开发服务,--port用于固定端口。不同构建工具的参数名可能不同,传参前看 scripts 里用的是什么。npm run build不是上线才跑,装完依赖后跑一次能提前发现模板语法、组件解析和样式导入问题。
# .env.development VITE_API_BASE_URL=/api VITE_USE_MOCK=true环境变量里,VITE_前缀是 Vite 暴露给前端代码的约定,没有前缀的变量不会进客户端。VITE_API_BASE_URL给请求封装用,VITE_USE_MOCK控制 mock 开关。生产环境对应.env.production,把 mock 关掉、把接口地址换成真实网关。环境变量改完要重启 dev 服务,热更新不一定能读到新值。
3. 接入 Element-Plus:Vue3 组件库的安装、注册与样式顺序
3.1 装包与全局注册:main.js 里那几行到底做什么
Element-Plus 是 Vue3 的组件库,不能和 Vue2 时代的 Element-UI 混用。装包时先确认工程依赖里没有旧的 element-ui,否则容易出现组件名冲突、样式互相覆盖。全局注册适合演示工程和内部工具,写法短、见效快;代价是打包体积偏大,生产项目更常见的是按需引入。
# 安装 Element-Plus npm install element-plus # 如果工程里残留 Vue2 的 element-ui,先确认是否还需要 npm ls element-ui --depth=0安装完成后在入口文件注册。全局引入要同时导入组件库和样式文件,样式导入顺序放在自定义样式之前,否则后面覆盖主题变量时会被组件库默认样式压住。
// main.js import { createApp } from 'vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' // 组件库基础样式 import App from './App.vue' import './styles/index.css' // 项目自定义样式放在后面 const app = createApp(App) app.use(ElementPlus) app.mount('#app')app.use(ElementPlus)做的是全局注册,注册后模板里可以直接写<el-button>、<el-table>,不需要每个页面单独 import。element-plus/dist/index.css是完整样式入口,漏掉它最常见的现象是按钮有结构没样式、表格错位。自定义样式放在组件库样式之后,覆盖顺序才正确。
3.2 按需引入:unplugin-vue-components 与 unplugin-auto-import 的配置
工程进入业务开发后,全量引入会让首屏包变大。常见做法是用 unplugin-vue-components 和 unplugin-auto-import 做自动导入,模板里写组件、脚本里写 ElMessage 这类方法时自动补 import。这个方案依赖构建工具配置,Vite 工程配置在 vite.config.js;如果工程不是 Vite,就看对应构建工具的插件写法,不要硬套。
# 按需引入所需开发依赖 npm install -D unplugin-vue-components unplugin-auto-import// vite.config.js import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import AutoImport from 'unplugin-auto-import/vite' import Components from 'unplugin-vue-components/vite' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' export default defineConfig({ plugins: [ vue(), AutoImport({ resolvers: [ElementPlusResolver()], dts: 'src/auto-imports.d.ts' // 生成类型声明,方便编辑器提示 }), Components({ resolvers: [ElementPlusResolver()], dts: 'src/components.d.ts' }) ] })AutoImport负责自动导入 API,Components负责自动注册组件,ElementPlusResolver是 Element-Plus 的解析器。dts生成类型声明文件,TypeScript 项目会用到;生成后不要手改,重新启动 dev 会刷新。按需引入后,如果某个组件在模板里不生效,先看终端有没有解析警告,再看配置文件是否被构建工具真正加载。
注意:按需引入和全局引入不要在同一入口重复写。两套方案同时存在时,容易出现样式重复、组件注册冲突,排查成本很高。
3.3 样式顺序与 Vue2 迁移坑:Element-UI 不能混进 Vue3
Vue3 项目里出现 Element-UI 的旧写法,是迁移阶段最常见的翻车点之一。Element-UI 面向 Vue2,按需引入常配 babel-plugin-component;Element-Plus 面向 Vue3,按需引入走 unplugin 系列。两者包名、样式入口、注册方式都不同,混用后典型现象是组件能渲染但样式错乱,或者控制台提示找不到某个旧组件。
| 对比项 | Element-UI | Element-Plus |
|---|---|---|
| Vue 版本 | Vue2 | Vue3 |
| 包名 | element-ui | element-plus |
| 全量样式 | theme-chalk/index.css | dist/index.css |
| 按需引入 | babel-plugin-component | unplugin-vue-components |
| 入口注册 | Vue.use | app.use |
样式覆盖也要讲顺序。主题变量、全局样式、页面局部样式按从外到内排列,不要在每个组件里重复 import 组件库样式。需要改主色时,优先用 CSS 变量覆盖,不要直接改 node_modules 里的文件,否则下次安装依赖就丢。迁移旧页面时,先把el-组件逐个对照 Element-Plus 文档确认属性变化,再处理样式,别一上来就大面积替换。
4. Mockjs 假数据落地:接口拦截、分页模板与 dev 开关
4.1 mockjs 放 devDependencies:安装与启用开关
Mockjs 的定位是开发阶段假数据,不应该进入生产包。安装时放 devDependencies,入口处用环境变量控制是否加载。Vue3 + Vite 工程里可以用import.meta.env.DEV判断,只在开发环境动态 import mock 文件。这样构建生产包时,mock 相关代码不会被打进去,接口请求会走真实地址。
# mockjs 只用于开发联调 npm install -D mockjs// main.js 或独立的 mock 入口 if (import.meta.env.DEV && import.meta.env.VITE_USE_MOCK === 'true') { import('./mock/index.js') // 动态导入,生产构建会剔除 }import.meta.env.DEV是 Vite 注入的开发环境标记,VITE_USE_MOCK是自定义开关。动态 import 的好处是生产构建时不会把 mock 文件打进主包。开关不要写死为 true,联调阶段可以随时关掉,避免出现「接口一直返回假数据、以为后端没通」的误会。
4.2 写一个分页列表接口:Mock.mock 的 url、type、template
Mockjs 的核心写法是Mock.mock(url, type, template)。url 要和请求封装里的路径一致,type 用 get 或 post,template 可以是对象,也可以是函数。分页列表建议用函数,从 options.url 里解析 page 和 pageSize,再返回对应条数。这样前端分页组件切页时,mock 返回的数据会跟着变,不会永远停在第一页。
// src/mock/user.js import Mock from 'mockjs' const Random = Mock.Random // 生成一批用户数据,供列表接口复用 const userList = Array.from({ length: 86 }).map((_, index) => ({ id: index + 1, name: Random.cname(), email: Random.email(), status: Random.pick(['enabled', 'disabled']), createdAt: Random.datetime('yyyy-MM-dd HH:mm:ss') })) Mock.mock(/\/api\/user\/list/, 'get', (options) => { // 从 url 查询串里取分页参数 const query = new URL(options.url, 'http://localhost').searchParams const page = Number(query.get('page') || 1) const pageSize = Number(query.get('pageSize') || 10) const start = (page - 1) * pageSize return { code: 0, message: 'ok', data: { list: userList.slice(start, start + pageSize), total: userList.length, page, pageSize } } })Mock.mock的第一个参数用正则,可以匹配带查询串的 url;如果用字符串,查询串变化时可能匹配不上。options.url是完整请求地址,URL解析出 page 和 pageSize。userList.slice按页截取,total返回总数,前端分页组件才能算出总页数。数据生成放在 mock 文件顶层,避免每次请求都重新造一批,切页时数据才稳定。
注意:Mockjs 主要拦截 XMLHttpRequest。项目里如果用 axios 默认适配器,一般能拦住;如果请求封装改成了 fetch,Mockjs 可能不生效,这时要么换回 XHR 适配,要么改用构建工具侧的 mock 插件。
4.3 请求封装与代理边界:/api 前缀、baseURL 与 rewrite
mock 能不能生效,很多时候不是 Mockjs 的问题,而是请求路径和代理配置打架。前端请求封装通常设一个 baseURL,比如/api;mock 的 url 也要带同样的前缀。开发服务器代理则用于关掉 mock 后把/api转发到真实后端。三者要对齐:请求路径、mock 匹配规则、代理前缀。
// src/utils/request.js import axios from 'axios' const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL || '/api', timeout: 10000 }) export default request// vite.config.js 中的代理配置 server: { proxy: { '/api': { target: 'http://127.0.0.1:8080', // 真实后端地址,按实际环境改 changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } }baseURL决定请求最终拼出来的路径,mock 匹配规则要能覆盖这个路径。代理里的changeOrigin用于调整请求头中的 host,rewrite用于去掉/api前缀。联调顺序建议是:先开 mock 跑通页面,再关 mock 开代理对接后端。不要两边同时开,否则请求被 mock 拦住,代理永远收不到流量。
5. 避坑排查:Vue3 + Element-Plus + mockjs 跑不起来的 5 个现场
5.1 现象:npm install 报 ERESOLVE peer dependency
现象是安装阶段直接失败,终端提示 peer dependency 冲突,常见于 Element-Plus 和某个旧插件对 Vue 版本的要求不一致。原因通常是工程里同时存在 Vue2 时代依赖,或者锁文件缺失导致 npm 重新解析了版本范围。解决不是无条件加--force,而是先看冲突包是谁。
# 查看冲突来源 npm ls vue --depth=1 # 确认是旧依赖后,移除或替换 npm uninstall element-ui # 临时绕过只适合确认问题,不适合长期使用 npm install --legacy-peer-deps先定位冲突包,能删就删,能升级就升级。--legacy-peer-deps只是让安装继续,不解决运行时冲突;--force更激进,容易把不兼容的包硬装进去。这类问题我踩过不止一次,血泪经验是:先看npm ls,再决定要不要动锁文件。
5.2 现象:页面白屏,控制台报 Failed to resolve component
现象是浏览器白屏,控制台提示某个el-组件无法解析。原因通常是 Element-Plus 没注册、按需引入插件没生效,或者组件名写错。解决先确认入口有没有app.use(ElementPlus),再确认构建配置有没有加载 resolver。
// 全局注册的兜底检查 import ElementPlus from 'element-plus' app.use(ElementPlus)如果走按需引入,检查 vite.config.js 是否真的被 Vite 读取,插件数组里有没有Components和ElementPlusResolver。改完配置要重启 dev 服务,热更新不会重新加载构建配置。
5.3 现象:Element-Plus 样式不生效或按钮错位
现象是组件结构出来了,但按钮没有背景色、表格边框错位、弹窗位置不对。原因多半是样式入口没导入,或者自定义样式顺序压在了组件库前面。解决先补element-plus/dist/index.css,再调整 import 顺序。
import 'element-plus/dist/index.css' // 先组件库 import './styles/index.css' // 后项目样式如果用了按需引入,确认 resolver 是否自动带样式;有些工程需要额外配置importStyle。不要直接改 node_modules 里的样式文件,换台机器重新安装就丢了。
5.4 现象:mock 接口 404 或请求打到真实后端
现象是页面请求列表失败,Network 里看到/api/user/list返回 404,或者请求直接发到了后端地址。原因通常是 mock 文件没加载、url 匹配规则不一致、请求用了 fetch,或者代理优先级高于 mock。解决先看入口的动态 import 有没有执行,再看请求路径和 mock 正则是否对得上。
// 确认 mock 文件被引入 if (import.meta.env.DEV && import.meta.env.VITE_USE_MOCK === 'true') { import('./mock/index.js') }请求路径带查询串时,mock 的 url 用正则更稳。关掉 mock 再开代理,不要两边同时开。用 fetch 的工程要换方案,Mockjs 对 fetch 的拦截并不可靠。
5.5 现象:端口被占用或热更新失效
现象是npm run dev启动后端口被占,或者改了代码页面不刷新。原因可能是上一次 dev 进程没退干净,或者端口被其他服务占用。解决先看终端输出的实际端口,再决定是换端口还是杀进程。
# 查看端口占用,按实际端口替换 lsof -i :5173 # 启动时显式换端口 npm run dev -- --port 5174热更新失效时,先确认文件在 src 目录内,再检查编辑器有没有开启安全写入。某些情况下删除 node_modules/.vite 缓存再启动也能恢复。不要一上来就重装依赖,先看终端和浏览器控制台。
6. 装完怎么验证:三条命令、一张检查表和一次回归
6.1 三条命令跑完再改代码
装完依赖后不要直接进业务页面,先跑三条命令做回归。第一条启动 dev,确认编译通过;第二条请求 mock 接口,确认假数据能返回;第三条构建生产包,确认 mock 不会被打进去。
# 1. 启动开发服务,观察终端是否有编译错误 npm run dev # 2. 请求 mock 分页接口,确认返回结构和分页字段 curl "http://localhost:5173/api/user/list?page=1&pageSize=10" # 3. 构建生产包,确认构建阶段没有组件解析问题 npm run build && npm run previewcurl的地址要换成终端实际输出的端口。返回里重点看code、data.list、data.total三个字段,分页组件能不能工作就看它们。构建命令能过,说明模板里的 Element-Plus 组件至少被正确解析;preview 再打开一次,确认生产模式没有白屏。
6.2 一张检查表收尾
| 检查项 | 通过标准 | 不通过先看 |
|---|---|---|
| Node 与 npm | 版本和工程要求一致 | package.json engines、.nvmrc |
| 依赖安装 | 无 ERESOLVE 报错 | npm ls vue、锁文件 |
| 组件注册 | 页面能渲染 el-button | main.js、resolver 配置 |
| 样式加载 | 按钮和表格样式正常 | index.css 导入顺序 |
| mock 开关 | dev 环境返回假数据 | VITE_USE_MOCK、mock 入口 |
| 生产构建 | npm run build通过 | 组件解析、环境变量 |
从那以后我每次拿到标注「环境已经配好」的 vue3-demo,都先跑一遍 Node 版本、依赖锁、mock 开关这三项,再动业务代码。这套 Vue3 框架加 Element-Plus 加 Mockjs 的组合,省掉的是脚手架和假数据接线的时间,真正要盯的是本机环境和请求路径。需要这套已配好环境的演示工程时,按资源页说明获取即可。希望帮到你。
本文还有配套的精品资源,点击获取