1. 新建前端pnpm(vue js ) 仿若依项目(一)
- pnpm 创建 Vue3 JavaScript 项目
- 目录、请求、登录、布局、权限逻辑对齐Ruoyi‑Vue
- 两套模式:①本地 Mock 模拟数据 ②代理访问真实后端接口
- 技术栈:Vue3 + Vue‑Router4 + Pinia + Element‑Plus + Axios + vite‑plugin‑mock
c
# 1. 确保已安装 Node.js(建议 18+)和 pnpm
node -v
pnpm -v
# 2. 安装 pnpm(如未安装)
npm install -g pnpm
# 3. 用 Vite 创建项目(推荐)
pnpm create vite my-app
# 选择框架:React / Vue / Vanilla 等
# 选择语言:TypeScript / JavaScript
# 4. 进入目录并安装依赖
cd my-app
pnpm install
# 5. 安装 element‑plus 界面库、axios 请求库、mock 模拟接口库
pnpm add element-plus axios
pnpm add -D vite-plugin-mock mockjs
# 6. 启动开发服务器
pnpm dev
1.1. 创建项目
打开终端执行
c
# 使用pnpm create vue脚手架
pnpm create vue@latest ruoyi‑vue3‑js‑demo
交互选项严格按照下面选
c
# 使用pnpm create vue脚手架
✔ Project name: ... ruoyi‑vue3‑js‑demo
✔ Add TypeScript? ... No
✔ Add JSX Support? ... No
✔ Add Vue Router for Single Page Application development? ... Yes
✔ Add Pinia for state management? ... Yes
✔ Add Vitest for Unit Testing? ... No
✔ Add an End‑to‑End Test Solution? ... No
✔ Add ESLint for code quality? ... Yes
✔ Add Prettier for code formatting? ... Yes


选项:跳过所有示例代码,创建一个空白的 Vue 项目?
- Yes:完全空白项目,没有脚手架自带示例页面
- No:保留脚手架自带示例代码
👉 选择 No(光标现在已经在 No 上,直接按回车即可)
选 No 会生成默认示例文件,后续我们手动删除这些示例文件,照着教程新建后台项目代码;
如果选 Yes,项目文件会很少,也可以用,但新手不推荐。
按回车完成项目创建。

进入项目文件夹、安装基础依赖、安装 element‑plus 界面库、axios 请求库、mock 模拟接口库、图标包库。等待全部安装完成。
c
cd Szyt
pnpm install
pnpm add element-plus axios
pnpm add -D vite-plugin-mock mockjs
pnpm add @element-plus/icons-vue
1.2. 调整目录结构(完全对标若依)
删除脚手架自带多余示例文件,最终目录:
ruoyi‑vue3‑js‑demo
├── .env.development # 开发环境变量
├── .env.production # 生产环境变量
├── vite.config.js
└── src
├── api # 接口层(和若依一致)
│ ├── request.js # axios封装
│ └── user.js # 用户相关接口
├── assets
├── components
│ └── Layout # 后台主布局组件【侧边栏+头部+主内容】
│ ├── index.vue
│ ├── Sidebar.vue
│ ├── Header.vue
│ └── AppMain.vue
├── mock # 本地模拟接口
│ ├── index.js
│ └── user.js
├── router # 路由
│ └── index.js
├── store # pinia状态管理(替代Vuex)
│ ├── app.js
│ └── user.js
├── utils # 工具函数
│ └── auth.js # token读写
├── views # 业务页面
│ ├── login
│ │ └── index.vue
│ └── home
│ └── index.vue
├── App.vue
└── main.js
1.2.1. 清理脚手架自带多余文件(删掉下面文件)
- src/components 下面
- ✅
HelloWorld.vue删除 - ✅
TheWelcome.vue删除 - ✅
WelcomeItem.vue删除 icons文件夹保留不动(后续放图标可以用)
- src/views 下面
- ✅
AboutView.vue删除 - ✅
HomeView.vue删除
- src/stores 下面
- ✅
counter.js删除(这是脚手架示例 pinia,我们自己写 user、app)
router 文件夹不要删除 ,只后面修改里面
index.js的内容。App.vue、main.js 不要删,后续直接覆盖里面代码。
删除完成后,再开始新建下面这些文件夹(在 src 上右键新建文件夹):
c
src/api
src/mock
src/utils
src/components/Layout
src/views/login
src/views/home
1.2.2. 修改 vite.config.js
把文件全部替换成下面代码,开启 mock 插件,区分 mock 模式开关,可一键切换「本地 mock」/「真实后端接口」
c
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { viteMockServe } from 'vite-plugin-mock'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
viteMockServe({
mockPath: 'src/mock',
localEnabled: true, // true使用mock;false访问真实后端
prodEnabled: false
})
],
resolve: {
alias: {
// ✅ ESM新标准写法
'@': path.resolve(import.meta.dirname, './src'),
}
},
server: {
port: 8080,
open: true,
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
1.2.3. 环境变量
根目录新建 2 个环境文件
(1).env.development
c
VITE_APP_BASE_API=/api
# VITE_APP_USE_MOCK=true viteconfig读取这个变量也可以控制mock开关
(2).env.production
c
VITE_APP_BASE_API=/api
1.2.4. 修改 src/router/index.js
打开 src/router/index.js,全部替换为下面路由基础代码:
c
export default [
{
url: '/user/login',
method: 'post',
response: ({ body }) => {
const { username, password } = body
if (username === 'admin' && password === '123456') {
return {
code: 200,
msg: '登录成功',
data: { token: 'mock‑admin‑token‑123456' }
}
} else {
return { code: 500, msg: '账号密码错误' }
}
}
},
{
url: '/user/getInfo',
method: 'get',
response: () => {
return {
code: 200,
data: {
name: 'Admin',
avatar: '',
roles: ['admin']
}
}
}
}
]
1.2.5. 修改 src/main.js
打开 src/main.js,完整替换:
c
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')
1.2.6. 修改 App.vue
打开 src/App.vue,全部替换:
c
<template>
<router-view />
</template>
<script setup>
</script>
<style>
* {
margin:0;
padding:0;
box-sizing: border-box;
}
</style>
1.2.7. 登录页面 src/views/login/index.vue
新建文件 src/views/login/index.vue,复制全部代码:
c
<template>
<div class="login-container">
<el-card class="login-card">
<h2>系统登录</h2>
<el-form :model="loginForm" label-width="80px">
<el-form-item label="账号">
<el-input v-model="loginForm.username" placeholder="请输入账号"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="loginForm.password" type="password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleLogin" style="width:100%">登录</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</template>
<script setup>
import { reactive } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const loginForm = reactive({
username: '',
password: ''
})
const handleLogin = () => {
if (!loginForm.username || !loginForm.password) {
return alert('账号密码不能为空')
}
// 简单模拟登录成功
localStorage.setItem('token', 'admin-token')
router.push('/')
}
</script>
<style scoped>
.login-container {
width:100%;
height:100vh;
display:flex;
justify-content:center;
align-items:center;
background:#f0f2f5;
}
.login-card {
width:400px;
}
h2 {
text-align:center;
margin-bottom:24px;
}
</style>
1.2.8. 首页 src/views/home/index.vue
新建文件 src/views/home/index.vue
c
<template>
<div class="home-page">
<el-container style="height:100vh">
<el-aside width="220px" style="background:#304156">
<el-menu
default-active="1"
router
background-color="#304156"
text-color="#bfcbd9"
active-text-color="#409EFF"
>
<el-menu-item index="/">
<el-icon><House /></el-icon>
<span>首页</span>
</el-menu-item>
</el-menu>
</el-aside>
<el-container>
<el-header style="background:#fff;border-bottom:1px solid #eee;display:flex;justify-content:flex-end;align-items:center;padding:0 20px">
<el-button @click="logout">退出登录</el-button>
</el-header>
<el-main>
<el-card>
<h3>欢迎进入后台管理系统</h3>
</el-card>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script setup>
import { useRouter } from 'vue-router'
import { House } from '@element-plus/icons-vue'
const router = useRouter()
const logout = () => {
localStorage.removeItem('token')
router.push('/login')
}
</script>
<style scoped>
.home-page {
width:100%;
height:100%;
}
</style>
1.2.9. 添加路由守卫(权限拦截)
打开 src/router/index.js,在文件最底部 export default router 之前加入守卫代码,完整文件如下:
c
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/index.vue')
},
{
path: '/',
name: 'Home',
component: () => import('@/views/home/index.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
//路由守卫
router.beforeEach((to, from, next) => {
const token = localStorage.getItem('token')
if(to.path === '/login'){
next()
}else {
if(token){
next()
}else{
next('/login')
}
}
})
export default router
1.2.10. ESLint 规则
ESLint 规则不允许组件文件名直接叫index.vue,认为组件名需要多单词,代码本身可以正常运行,只是编辑器警告 。ESLint 代码校验警告(关闭这条 eslint 规则),
从 ESLint v9 开始默认使用 eslint.config.js(flat 扁平化配置,不再是旧版 .eslintrc.js),没有 extends,用数组格式 。
需要先安装依赖
c
# 示例,装eslint相关
pnpm add -D eslint eslint-plugin-vue
&emsp项目根目录找到 .eslintrc.js 文件,打开,在 rules 里面增加一行配置:保存文件,重启编辑器警告就消失,不用改文件名。
c
import { defineConfig, globalIgnores } from 'eslint/config'
import globals from 'globals'
import js from '@eslint/js'
import pluginVue from 'eslint-plugin-vue'
import pluginOxlint from 'eslint-plugin-oxlint'
import skipFormatting from 'eslint-config-prettier/flat'
export default defineConfig([
{
name: 'app/files-to-lint',
files: ['**/*.{vue,js,mjs,jsx}'],
languageOptions: {
globals: {
...globals.browser,
},
},
},
globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']),
js.configs.recommended,
...pluginVue.configs['flat/essential'], // vue插件配置放前面
// ✅ 自定义规则放插件之后!优先级最高,可以覆盖vue插件规则
{
name: 'app/custom-rules',
files: ['**/*.{vue,js,mjs,jsx}'],
rules: {
'no-unused-vars': 'warn',
'no-console': 'off',
'vue/multi-word-component-names': 'off',
}
},
// vite.config.js属于node文件,单独给node全局变量
{
files: ['**/*.config.js'],
languageOptions: {
globals: {
...globals.node
}
}
},
...pluginOxlint.buildFromOxlintConfigFile('.oxlintrc.json'),
skipFormatting,
])
1.2.11. 启动项目测试
打开终端,执行
c
pnpm dev
浏览器会自动打开页面。
访问逻辑:没有 token 自动跳转到登录页,登录成功进入首页,点击退出回到登录页。
现在项目基础框架已经跑通,后面可以再加:axios 请求、mock 接口、pinia 状态管理。

