news 2026/10/4 7:04:21

Vue 3项目从零搭建到部署全攻略:环境、路由、打包避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue 3项目从零搭建到部署全攻略:环境、路由、打包避坑指南

我一直觉得,Vue 项目的搭建是很多前端新人遇到的第一个"劝退点"。不是 Vue 本身难,而是从安装 Node.js、选脚手架、配路由、调代理到最终打包上线,中间每一步都可能冒出个报错把人卡住。你问"如何搭建一个vue项目",网上答案一大堆,但要么只讲一半,要么直接甩个命令让你复制,根本不知道背后发生了什么。

这篇文章我想换个方式,不只是在命令行里敲几条命令就完事,而是把从零到能上线一个 Vue 项目的完整链路走一遍,包括环境准备、脚手架选型、项目结构、路由配置、状态管理、HTTP 请求封装、打包优化以及常见的坑。目标只有一个:你照着做,能跑通;你理解了为什么,换个项目也能自己搞定。

内容适合正在学 Vue 的初学者、准备用 Vue 做毕业设计或外包项目的同学,以及想从前端切到全栈、需要自己从零搭项目的开发者。当然,如果你已经能熟练用 Vite 创建项目,这篇里的坑和原理部分也值得扫一眼,很多细节是平时文档里不会写的。

1. 动手之前,先把 Vue 项目的"地基"打好

很多人一上来就敲npm create vue@latest,结果连 Node.js 都没装对版本,装依赖的时候报一堆错。这个阶段最值得花时间,因为环境问题会伴随你整个开发周期。

1.1 你需要准备哪些开发环境

一个标准的 Vue 项目,开发环境核心就三样:Node.js、npm(或 pnpm/yarn)、一个趁手的编辑器。

Node.js 是 Vue 项目的地基,npm 是包管理工具,负责下载和管理项目依赖。安装 Node.js 的坑主要有两个:版本过高或过低,以及下载源导致依赖安装慢。

推荐用 LTS(长期支持)版本,不要追最新版。Vue 3 + Vite 这套组合在 Node 18 以上的 LTS 版本都跑得很稳。我自己踩过的坑是,在 Node 16 上跑 Vite 5 的项目,启动直接报Error: error:0308010C:digital envelope routines::unsupported,这就是 Node 版本和 Vite 版本不兼容造成的,升级到 Node 18 后问题消失。

编辑器首选 VSCode,装两个扩展就够用:Vue 官方推荐的 Vue Language Features (Volar)以及 TypeScript Vue Plugin。如果你用的是 Vue 2,才需要装 Vetur,Vue 3 项目里装了 Vetur 反而会干扰提示,建议禁用。

还有一个小细节,很多人会忽略:把 npm 的 registry 切换到国内镜像。不然下载node_modules的时候,一个几十 MB 的依赖在国外源上下半小时,体验非常差。切换方式是命令行执行npm config set registry https://registry.npmmirror.com,换完之后用npm config get registry验证。

注意:不要用 cnpm 代替 npm。cnpm 偶尔会出现依赖目录结构不对的问题,导致某些包运行时找不到文件。用官方 npm 加国内镜像最有保障。

1.2 为什么我建议新项目优先考虑 Vite 而不是 Webpack

Vue 官方在 2022 年之后,新项目的默认推荐就是 Vite。这个选型的核心原因只有一个:快。

Webpack 启动一个大型项目的开发服务器,冷启动常常要等 30 秒到几分钟,改一行代码刷新一次也要一两秒。而 Vite 利用了浏览器原生 ES Module 能力,开发服务器启动时不用打包整个项目,按需编译,冷启动秒级完成,热更新基本在几百毫秒以内。

Vite 在开发阶段快得多的原理,用一句话解释:Webpack 是把所有模块先打包成一个 bundle 再给浏览器执行;Vite 是在浏览器请求某个模块时,服务端实时把那个模块编译好返回,请求到哪里编译到哪里。

生产构建方面,Vite 默认用 Rollup 做打包,产物比 Webpack 时代的优化配置更好用。不过有两点要提前说明:Vite 只支持 ES Module 构建,旧浏览器需要额外插件处理;另外如果你的项目用了大量老第三方库,可能要找兼容方案。但 2025 年的今天,大多数情况都不太存在这种兼容问题了。

1.3 脚手架二选一:create-vue 还是 Vue CLI

Vue 官方脚手架有两个:create-vue(新一代)和@vue/cli(老一代)。建议新项目无脑选create-vue。

create-vue是基于 Vite + Vue 3 + 组合式 API 的官方方案,支持 TypeScript、JSX、Router、Pinia、Vitest、ESLint、Prettier 等功能的交互式选择。它是当前 Vue 生态最主流、最正规的起点。

@vue/cli已经进入维护模式,不再推荐用来创建新项目。如果你的课程设计、公司老项目必须用 Vue CLI,我也在最后加了一小节说明怎么创建和启动,方便你了解两者差异。

2. 创建项目实操:从命令行到看到第一个页面

这一章我们直接上手。拿create-vue为例,从输入命令到浏览器出现页面,整个过程大概 5 分钟内完成。

2.1 用 create-vue 创建项目,每一步选什么

首先打开命令行,进入你想存放项目的目录,执行下面这行命令:

npm create vue@latest

执行后,命令行会问你几个问题,我一个个说下选择思路:

  • Project name:输入项目名称,比如my-vue-app。注意 npm 包名不能有大写字母,建议全部小写加短横线。
  • Add TypeScript?:如果你刚入门,选 No 可以少碰类型报错;如果做正式项目,强烈建议选 Yes,Vue 3 + TS 是趋势。
  • Add JSX Support?:默认 No 即可,Vue 单文件组件模板足够日常使用,JSX 不是必选项。
  • Add Vue Router?:选 Yes。单页应用基本都要路由。
  • Add Pinia?:选 Yes。状态管理后面一定会用到。
  • Add Vitest?:选 No。单元测试框架,需要测试的项目再加不迟。
  • Add End-to-End Testing Solution?:选 No。端到端测试用 Playwright 或 Cypress,按需添加。
  • Add ESLint and Prettier?:建议 Yes,代码规范可以靠它自动约束。

回答完这些,脚手架会自动把基础项目生成到目录。接着执行:

cd my-vue-app npm install npm run dev

默认情况下开发服务器跑在http://localhost:5173,浏览器打开就可以看到 Vue 官方欢迎页。

2.2 项目目录结构逐层拆解

脚手架生成的项目目录长这样:

my-vue-app/ ├── node_modules/ # 依赖包,npm install 生成的 ├── public/ # 公共静态资源,打包时原样复制到根目录 ├── src/ │ ├── assets/ # 构建时处理的静态资源(图片、样式) │ ├── components/ # 公共组件 │ ├── router/ # 路由配置 │ ├── stores/ # Pinia 状态管理 │ ├── views/ # 页面级组件 │ ├── App.vue # 根组件 │ └── main.ts # 入口文件 ├── index.html # HTML 模板,Vite 的入口 ├── package.json # 项目元数据、依赖声明和脚本 └── vite.config.ts # Vite 配置文件

重点理解几个文件的作用:

main.ts是应用的入口,它做三件事:创建应用实例、注册插件(路由、状态管理等)、挂载到页面上的某个 DOM 节点。代码大致长这样:

import { createApp } from 'vue' import { createPinia } from 'pinia' import router from './router' import App from './App.vue' const app = createApp(App) app.use(createPinia()) app.use(router) app.mount('#app')

App.vue是根组件,所有页面最终都渲染在里面。router-view是路由出口,URL 变化时会自动切换在这个位置渲染的组件。

index.html是整个应用的 HTML 外壳,它的body里面只有一个<div id="app"></div>,Vue 实例会挂载到这个 div 上。Vite 开发时以它为入口,构建时注入打包好的 JS/CSS。

2.3 启动开发服务器,验证项目能跑起来

启动开发服务器命令是npm run dev。看到终端出现Local: http://localhost:5173/就说明成功了。浏览器打开后,修改src/views/HomeView.vue里的模板内容,保存,页面应该会即时更新。

开发服务器的核心优势是热模块替换(Hot Module Replacement,简称 HMR),修改代码后浏览器不用整页刷新,组件状态还能保留。Vite 的 HMR 速度在大型项目里优势更明显。

这里提前说一个常见问题:如果端口 5173 被占用,Vite 会自动往后面的端口尝试,终端会提示新端口。这个不是 bug,不要慌。

3. 项目骨架搭建:路由、状态管理、HTTP 请求

项目能跑起来只是第一步,一个真正的项目还需要搭建三条基础设施:路由负责页面跳转,状态管理负责跨组件共享数据,HTTP 请求封装负责与后端通信用。这三件套搭好后,业务代码就能往上面填了。

3.1 配置路由:基础路由、动态路由与拦截器

Vue Router 4 是 Vue 3 的官方路由。在src/router/index.ts里配置路由表,核心代码如下:

import { createRouter, createWebHistory } from 'vue-router' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', name: 'home', component: () => import('@/views/HomeView.vue') }, { path: '/about/:id', name: 'about', component: () => import('@/views/AboutView.vue') } ] }) export default router

三个关键概念说一下:

createWebHistory是 HTML5 History 模式,URL 看起来是http://localhost:5173/about,干净美观。还有一种createWebHashHistory是 hash 模式,URL 里带#。History 模式在开发环境一切正常,但打包部署到 Nginx 等服务器时,如果没配置 fallback,刷新二级页面会 404。这点在「5. 打包上线」部分细说。

动态路由:/about/:id中的:id是路由参数,组件里用route.params.id获取。页面跳转用router.push({ name: 'about', params: { id: 123 } }),这样代码里不用硬编码 URL。

路由拦截器是很多业务场景的必需品,最典型的是登录鉴权。在访问需要登录的页面时,如果未登录,跳到登录页;已登录才能继续。实现方式是在路由配置里加一个meta字段,然后调用router.beforeEach做全局守卫:

router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') if (to.meta.requiresAuth && !token) { next({ name: 'login' }) } else { next() } })

这个逻辑不复杂,但注意判断顺序:没有requiresAuth标记的公共页面应该直接放行,否则会影响正常访问。

3.2 状态管理:Pinia 还是 Vuex

如果你看的热搜词里出现了"vue pinia vs vuex",说明你在关注状态管理的选型。结论简单直接:新项目用 Pinia,老项目才看 Vuex。

Pinia 是 Vue 官方在 Vuex 之后推出的新状态管理库,创建项目时直接可勾选集成。对比 Vuex 4,Pinia 的优势很直观:

对比维度PiniaVuex
学习成本低,接近直接用对象高,需要理解 state/mutations/actions 概念
TypeScript 支持原生好需要写额外类型代码
代码量少多
官方维护活跃维护模式

Pinia 的 stores 定义简单多了,在src/stores/counter.ts里这样写:

import { defineStore } from 'pinia' import { ref } from 'vue' export const useCounterStore = defineStore('counter', () => { const count = ref(0) function increment() { count.value++ } return { count, increment } })

组件里使用:

<script setup lang="ts"> import { useCounterStore } from '@/stores/counter' const counter = useCounterStore() </script> <template> <button @click="counter.increment()">{{ counter.count }}</button> </template>

这种 Setup 风格写法跟写组合式函数很像,非常直观。

3.3 封装 Axios,统一处理请求和 Token

几乎每个 Vue 项目都要跟后端接口打交道。前端最主流的 HTTP 库是 Axios。直接用会产生很多重复代码,所以通常会做一层封装,把baseURL、超时时间、请求头、Token 注入和错误提示集中处理。

先在项目里安装 axios:

npm install axios

在src/utils/request.ts里封装一个实例:

import axios from 'axios' import { ElMessage } from 'element-plus' import router from '@/router' const request = axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL, timeout: 10000 }) // 请求拦截器:自动携带 token request.interceptors.request.use(config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config }) // 响应拦截器:统一处理业务错误和登录过期 request.interceptors.response.use( response => { const res = response.data if (res.code !== 200) { ElMessage.error(res.message || '请求失败') return Promise.reject(new Error(res.message)) } return res }, error => { if (error.response?.status === 401) { localStorage.removeItem('token') router.push({ name: 'login' }) } ElMessage.error(error.message || '网络错误') return Promise.reject(error) } ) export default request

这套封装解决三个问题:

Token 注入:登录后后端返回 token,前端存到 localStorage 或 cookie,后续每个请求自动带上。这样就不用每个接口手动写一遍 header。

统一错误提示:后端返回的业务错误码,由响应拦截器统一弹出提示,业务代码里就不用重复写alert。

登录过期处理:请求返回 401 时,统一清除本地登录状态并跳转登录页。

注意:搜索热搜里还有个"vue前后端分离请求token处理",其实思路就是上面这套。唯一要提醒的是,token 别放在localStorage里存敏感数据,如果项目对安全要求高,可以用 HttpOnly Cookie 方案,防止 XSS 窃取。不过这个属于进阶项,大多数内部系统用 localStorage 问题不大。

这里的ElMessage是 Element Plus 组件库的轻提示,如果你项目不用 Element Plus,换成自己的 UI 组件库提示方式即可。

4. 提升开发效率:路径别名与环境变量

项目变大以后,组件之间互相引入的路径特别容易写错。写../../../../components/xxx这种事,不仅丑而且脆,随便移动下目录结构就全挂了。这个坑可以通过配置路径别名来解决。

4.1 配置@别名,告别一长串相对路径

在vite.config.ts里配置@别名指到src目录:

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { fileURLToPath, URL } from 'node:url' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } } })

配置后,import HomeView from '@/views/HomeView.vue'就能正常工作。这一步还有一个隐藏问题:如果项目使用了 TypeScript,还需要在tsconfig.json里同步配置 paths,否则 VSCode 会飘红报找不到模块。

{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] } } }

4.2 环境变量:不同环境用不同配置

开发环境、测试环境、生产环境的 API 地址通常不一样。把配置写死在代码里,换环境就要改代码,非常蠢。Vite 的环境变量机制可以解决。

在项目根目录创建.env.development和.env.production:

# .env.development VITE_API_BASE_URL=/api VITE_APP_TITLE=开发环境
# .env.production VITE_API_BASE_URL=https://api.example.com VITE_APP_TITLE=生产环境

代码里通过import.meta.env.VITE_API_BASE_URL读取。Vite 规定只有以VITE_开头的变量才会暴露给客户端代码,其他前缀不会,这是安全设计,防止敏感配置泄漏到浏览器。

4.3 代码规范:用 ESLint + Prettier 解放双眼

利益于 create-vue 创建项目时如果勾选了 ESLint 和 Prettier,项目里已经带有完整配置。npm run lint可以检查代码,npm run format可以自动格式化。

很多新手觉得 lint 是找茬,我的建议是反过来看待它:lint 强制统一的代码风格,多人协作时最大的价值就是减少"你这个括号怎么不换行"这类完全没有意义的摩擦。格式化交给 Prettier 后,提交到 git 里的代码diff也能变得干净,review 起来舒服很多。

5. 打包上线那些坑:布局异常、路由 404、依赖报错

很多人在本地开发一切正常,一打包部署就出各种问题。我按热搜词整理了几个高频问题,逐个说原因和解决方案。

5.1 打包后布局异常的常见原因

热搜词里有"vue 打包后 布局异常",这是几乎每个 Vue 新手都会遇到的一类问题。常见的表现是:本地开发显示正常,npm run build后部署上去,样式乱了、图片裂了、路由页面空白。

核心原因大概率是资源路径写死了绝对路径。默认情况下 Vite 打包后的资源路径以/开头,如果你的应用部署在域名子路径下,比如https://example.com/my-app/,那/assets/index.js就会去域名根目录找资源,自然找不到。

解决方案:在vite.config.ts里配base:

export default defineConfig({ base: '/my-app/' // 部署到子路径时配置,根域名部署就保持默认 })

另外,如果项目里直接用了<img src="/images/logo.png">这种绝对路径写法,也会出现同样问题。改成下面这种或者用assets目录引入的方式:

<img src="@/assets/logo.png">

5.2 路由 history 模式刷新 404

这个问题几乎每个用了createWebHistory的项目都会踩到。开发环境没问题,打包部署到 Nginx 后,访问首页正常,一旦访问https://example.com/about并刷新,就出现 404。

原因在于:前端路由是浏览器端实现的,服务器上并没有真实的/about目录。默认 Nginx 收到请求后在磁盘找对应文件找不到,就返回 404。

解决方案是配置 Nginx 的 try_files,把所有路由请求都 fallback 到index.html:

location / { try_files $uri $uri/ /index.html; }

注意:用了这个配置后,所有未知路径都会返回index.html,就不会出现后端接口路径也被 history fallback 的情况。但前提是接口 API 路径和前端路由是不同前缀,比如/api的请求单独设置 location 不走 fallback。

如果你用的是宝塔面板这类图形化管理工具,可以在网站配置里找到伪静态设置的入口,加上上面的规则即可。

5.3 依赖安装报错处理

热搜词里有 "ignored build scripts" 之类的问题,其实常见报错场景还有这些:

cpu-features、esbuild、ssh2这类包在安装时提示 "ignored build scripts",是 npm 6.4 之后为了安全引入的机制,不会影响正常使用。真正常见的坑是下面这些。

node_modules装到一半报ENOSPC指磁盘空间不足;报EACCES是权限问题,macOS/Linux 下在命令前加sudo,但更推荐用 nvm 装 Node 以避免这种情况;报ERESOLVE unable to resolve dependency tree是依赖版本冲突,最优先看是不是 npm 版本太老,或尝试删掉node_modules和package-lock.json后重新安装。

遇到依赖报错,我推荐的排查顺序是:

  1. 看报错关键字,判断是权限、网络还是版本问题
  2. 确认 Node.js 版本,node -v查看
  3. 删掉node_modules和package-lock.json,重新npm install
  4. 换用npm cache clean --force清理缓存后重试
  5. 最后再考虑是不是某个第三方包本身有问题,查 GitHub Issues

注意:不要一上来就删除package-lock.json。这个文件锁定了依赖版本,如果团队合作时删掉它,别人npm install可能装出不同版本导致行为不一致。只有在确认是依赖树冲突且其他方式无效时才考虑删。

6. 高频问题排查速查表

以下是基于热搜和常见社区提问整理的排查速查表,方便按图索骥:

现象可能原因解决方案
npm run dev启动报错Node 版本过老或过新用 nvm 切换到 Node 18 以上 LTS 版本
页面样式完全没加载CSS 资源引用路径不对检查vite.config.ts中的 base 配置
图片裂掉public 目录下绝对路径引用改用@/assets/或相对路径引入
路由刷新 404使用了 history 模式但服务器未配置 fallbackNginx 配置 try_files 规则
请求后端接口跨域前后端不同源开发环境配 Vite proxy,生产环境由后端配 CORS
页面加载白屏,控制台报 JS 错误可能是部署后 JS 路径 404 或语法兼容问题检查网络请求资源路径,确认 base 配置和浏览器兼容目标
依赖装完后项目跑起来报模块不存在node_modules 损坏删除 node_modules,重新 npm install
热更新失效,改代码页面不刷新Vite HMR 遇上未处理大文件或特定插件重启 dev server 试试,偶尔有用
打包后首屏加载过大没有做代码分割路由懒加载、按需引入 UI 组件库,可用 Vite 构建分析插件确认
多个文件格式转换报错第三方库只在浏览器环境可用查找该库的 SSR/构建兼容说明,考虑动态 import

这个表格我尽量挑的都是高频真实问题,不是概念问题。每条都是我在项目或教学里亲眼看到过的。

7. 老项目怎么办:Vue CLI 项目创建与迁移思路

如果公司或毕设题目规定用 Vue CLI,或者手上有一个 Vue 2 老项目要维护,还是需要知道怎么操作。

创建方式:

npm install -g @vue/cli vue create my-vue-cli-app

vue create同样有交互式选项,创建后npm run serve启动开发服务器,npm run build打包。Vue CLI 默认走 Webpack,因为配置复杂,vue.config.js 里可以自定义打包配置。

我个人的实际建议是:如果是从零开始的个人项目,别再用 Vue CLI 了。长期看 Vite 的生态和性能优势会更明显。老项目迁移也不建议一步到位重写,可以渐进式地在 Vite 环境里跑老代码,官方有专门的迁移指南,难点主要在 Webpack 插件换成 Vite 插件、公共路径和构建产物差异调整。

8. Vue 生态拓展:每个项目都少不了的"周边"

把项目跑通只算完成了骨架,真实业务场景里还有一堆需求必须面对,单独列一节说。

8.1 组件库与 UI 方案

Element Plus 在 PC 端中后台项目里用的人最多,组件全、文档好、社区大。如果你的项目偏移动端,可以用 Vant;如果追求动手能力的提升,也可以自己封装基础组件。组件库引入了之后,建议在main.ts里使用按需引入,不要app.use(ElementPlus)一次性全量引入,这会极大增加打包体积。

8.2 视频播放:Vue 配合 m3u8 流媒体

热搜词里反复出现 "vue播放m3u8",很多人以为要在 Vue 里自己写播放逻辑。其实方案很简单:m3u8 是 HLS 流媒体协议的视频文件格式,浏览器原生不直接支持,需要引入 hls.js 或使用 video.js 加 hls 插件。在 Vue 项目里,封装一个HlsPlayer.vue组件是常见做法。

思路大致是:组件内部创建一个<video>元素,用 hls.js 绑定播放地址,销毁时调用hls.destroy()防止内存泄漏。watch 到src变化时重新加载播放器。

这个需求常见于监控系统、课程点播、大屏展示,配xgplayer这类播放器会更快。

8.3 地图与可视化:Vue 里的地图组件

在一些项目中需要接入地图(腾讯地图、高德地图、百度地图),如果用 Vue 生态,推荐vue-baidu-map或官方地图 SDK 的 JS API 手动封装。如果是腾讯地图,也有对应的 Vue 组件封装思路。

地图组件容易踩的坑主要是 key 鉴权、地图容器尺寸(需要给容器固定高度)以及初始化时机(要在页面渲染完成后再初始化地图,用onMounted)。

可视化方面,如果要做配电工艺图、矩阵树图这类数据可视化业务,ECharts 加上 Vue 封装的vue-echarts是最常用的方案。ECharts 没有组件化,直接绑定到一个 div 上,注意要在onMounted或等数据返回后初始化。

8.4 数据表格导出:多表格导出 Excel

"vue 多个表格导出一个 excel" 这个需求在实际项目里特别常见,比如一个账期有多张账单,希望一次导出成一个 Excel 文件,每个 sheet 对应一张表。方案上通常用xlsx或exceljs库。

思路是:先用xlsx.utils.json_to_sheet把每个表格的数据转成 sheet,再XLSX.utils.book_append_sheet把多个 sheet 加进同一个 workbook,最后XLSX.writeFile写入文件。要注意文件名称需要有.xlsx后缀,以及中文表头需要自己在数据层面映射好。

8.5 Vue 和 Spring Boot:前后端分离的黄金组合

热搜里那块 "springboot vue前后端分离" 是很典型的企业级技术组合。Vue 负责前端页面和交互,Spring Boot 负责后端接口,通过 HTTP 请求通信。

开发阶段用 Vite 的 proxy 代理解决跨域:

export default defineConfig({ server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } })

这个配置的意思是:前端发的/api/xxx请求,代理到后端http://localhost:8080/api/xxx,这样浏览器觉得是同源的。生产环境则通常由 Nginx 统一做反向代理,把/指向前端静态文件,/api指向后端服务。

9. 新手常见面试考点:除了搭建还会被问什么

既然热搜里有 "vue面试题",说明不少读者是边学边找工作。搭建项目之余,有几个面试高频点直接相关,这里简单梳理一下。

9.1 Angular 和 Vue 有什么区别

Angular 是完整框架,内置依赖注入、RxJS、模块体系,学习曲线陡;Vue 是渐进式框架,核心只关注视图层,路由、状态管理这些可以按需选择。Vue 的模板语法更贴合 HTML,Angular 更偏 TypeScript 和依赖注入思维。选择上:中小型项目用 Vue 更轻快,大型企业级项目 Angular 更强约束力但学习成本也更高。

9.2 路由传参的几种方式

Vue Router 传参有三种方式:query(URL 问号后面)、params(路径参数)、state(历史记录状态里)。

// query 方式 router.push({ path: '/list', query: { page: 1 } }) // params 方式,需要路由配置 path: '/detail/:id' router.push({ name: 'detail', params: { id: 2 } })

query 参数刷新页面还在,params 参数如果用path跳转且路由写的是:id,也能保留在 URL 上。但如果只用name跳转且路由没有写参数,刷新就丢了。这个差别是面试常考点。

9.3 透传、Composable、v-model 这些开发细节

热搜里有几个比较进阶的词:透传、composable、v-model在组件里的用法。这里简单点一下:

透传指组件上没被声明为 props 或 emits 的属性,会自动传到组件根元素上。v-bind="$attrs"在封装组件时很有用,比如写一个自定义按钮时,用户传的disabled、style等不需要组件内声明也能生效。

Composable 是 Vue 3 组合式 API 的核心用法,把有状态的逻辑抽出来复用,比如useDebounce、useTable、usePermission,本质上就是一个返回响应式数据的函数。这套思维在写业务代码时非常能提升复用程度。

v-model在组件上的用法:子组件里defineModel()(Vue 3.4+ 语法),或者手动实现modelValueprop 和update:modelValue事件的组合。灵活使用这个,可以让表单组件双向绑定得非常顺手。

9.4 Vue 3 项目为什么要用 Volar

再补一个非常小但很细节的点:Vue 3 项目里官方推荐的 Volar 取代了 Vetur。Volar 对 TypeScript 支持更好,模板内类型检查也更完整。如果你在 VSCode 里配了 Vetur 而代码提示一直不对,果断禁用 Vetur,装回官方推荐的 Vue Language Features (Volar)。

10. 真实项目的目录规划:比脚手架默认结构更进一步

最后这部分值得单独考虑。实际业务项目里,脚手架生成的默认目录不够支撑复杂业务,需要稍作规划。

我比较常用的分层大概是:

src/ ├── api/ # 每个模块的接口请求 ├── assets/ # 静态资源 ├── components/ # 公共组件(按业务模块分子目录) ├── composables/ # 组合式函数 ├── directives/ # 自定义指令 ├── layout/ # 页面布局框架 ├── router/ # 路由配置 ├── stores/ # 全局状态 ├── styles/ # 全局样式变量 ├── utils/ # 工具函数 ├── views/ # 页面 └── types/ # TypeScript 类型定义

api目录单独抽出来的原因很实际:页面组件里不要直接写request.get('/list'),而是把所有接口调用收拢到api/user.ts、api/order.ts这类文件里。后端接口路径一变,只改一个文件就行,不用全局搜。

composables是 Vue 3 组合式 API 的精华位置。比如一个表格页面常见逻辑——拉数据、loading、分页、筛选——可以抽成useTable组合函数。项目里这种逻辑复用越多,代码越干净。

加粗一下:目录规划没有绝对标准,只要团队里所有人都能快速找到对应代码,就算合理。

最后再分享一个我自己的使用习惯:开新项目时,先花 10 分钟把路由、请求封装、状态管理和目录结构搭好,再写业务。这 10 分钟的收益,会在你整个开发周期里持续放大。别嫌麻烦,也别上来就照着 demo 狂写业务代码——等代码堆到几千行再改结构,那才叫真的麻烦。这套流程你跟着走完一遍,基本就能脱离教程独立开工了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/4 7:04:05

HLS实现二维FFT图像处理:从算法设计到Zynq上板全流程

每年暑假的Xilinx暑期学校都是集中肝项目的好时候。我当时抽到的项目二是“通过HLS实现二维傅里叶变换(2D FFT)及图像数据读入读出”&#xff0c;听名字很学院派&#xff0c;实际做完才发现&#xff0c;它几乎把HLS开发最常见的痛点是挨个打了一遍&#xff1a;算法怎么写、数组…

作者头像 李华
网站建设 2026/10/4 7:03:45

老系统迁移无文档?从代码逆向提取PRD的实战指南

1. 接手一个没有文档的老系统&#xff0c;到底难在哪很多做企业级开发的朋友都遇到过这种局面&#xff1a;领导拍着你的肩膀说&#xff0c;这套系统跑了五六年了&#xff0c;现在要迁移到新架构&#xff0c;你先把需求文档整理出来。你打开代码仓库一看&#xff0c;别说需求文档…

作者头像 李华
网站建设 2026/10/4 7:03:11

偏振光栅衍射效率测量:斜入射条件下的公式修正与实操指南

做光栅衍射实验的人都知道&#xff0c;正入射条件只是理想化模型&#xff0c;真正装到系统里&#xff0c;入射角几乎不可能正好是零。这个项目之所以有意思&#xff0c;在于把"入射角不为零"和"偏振光栅"这两个变量叠在一起之后&#xff0c;原本在普通光栅…

作者头像 李华
网站建设 2026/10/4 7:03:02

滑动t检验的Matlab实现:气候水文突变检测与判读指南

做气候或水文序列突变检测的&#xff0c;十有八九开口就是Mann-Kendall检验。MK确实好用&#xff0c;但真到要判定具体哪一年发生突变的时候&#xff0c;它的UF/UB曲线经常给你画出一大片交叉区&#xff0c;反而让人犯难。相比之下&#xff0c;滑动t检验的思路朴素得多——把序…

作者头像 李华
网站建设 2026/10/4 6:59:55

ANSYS Workbench高斯热源仿真实战指南

1. 项目概述&#xff1a;为什么在Workbench里做增材制造高斯热源仿真不是“选做题”&#xff0c;而是“必答题”我在金属3D打印工艺开发组干了八年&#xff0c;从最早的SLM设备调参员一路做到现在带三个仿真小组的负责人。每天早上第一件事不是看生产报表&#xff0c;而是打开A…

作者头像 李华