.github/workflows/ci.yml
Vue 生态玩明白了,才敢投大厂前端岗
去年秋招被面到 Vue 响应式原理直接挂掉后,我默默删掉了简历里“精通 Vue”那行字。现在大三下,趁着秋招前最后的窗口期,我把自己关在家里两个月,从零搭了个完整的 Vue3 + TypeScript + Vite 项目,顺便把整个生态摸了个底朝天。今天这篇就当是阶段性复盘——不讲八股文,只聊实战中踩过的坑、调过的动画、和后端联调时差点掀桌的瞬间。
起因:产品经理说要“丝滑交互动效”
事情得从上个月说起。我在远程实习的 startup 团队接了个新需求:做一个类似 Notion 的文档协作工具原型,重点要求“交互丝滑、动画自然”。PM 甚至甩了句:“参考 Figma 那种流畅度。”我表面点头,心里已经翻白眼——Figma 是 Electron + Canvas,咱这 Web 端用 Vue,能一样?但 deadline 在即,只能硬着头皮上。
我本来想直接上 GSAP 或 Anime.js,但转念一想:既然是 Vue 项目,不如深入用好它的生态,看看 Composition API + <Transition> + 自定义指令能不能搞定。结果这一试,直接把我拉进了 Vue 深水区。
为什么没选 React?真不是偏见
很多人问我:“现在大厂不是都用 React 吗?你干嘛死磕 Vue?”
说实话,我 React 也写过(课程项目+小 side project),它确实灵活,生态庞大。但这次选 Vue,一是团队技术栈统一,二是——开发体验真的爽。
Vite 冷启动 200ms,HMR 几乎无感;SFC(单文件组件)把 template/script/style 封装在一起,逻辑和视图高度内聚;再加上 Composition API,代码组织比 Options API 清晰太多。尤其在做复杂交互动画时,响应式数据驱动 DOM 变化,比手动操作节点舒服一百倍。
当然,React Hooks 也很强大,但对我这种喜欢“声明式动画”的人来说,Vue 的 <Transition> 和 <TransitionGroup> 简直是开箱即用的神器。比如下面这个列表项删除动画:
<template>
<TransitionGroup name="list" tag="ul">
<li v-for="item in items" :key="item.id" class="item">
{{ item.text }}
<button @click="remove(item.id)">×</button>
</li>
</TransitionGroup>
</template>
<style scoped>
.list-move,
.list-enter-active,
.list-leave-active {
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateX(30px);
}
.list-move {
transition: transform 0.5s ease;
}
</style>
就这么几行,列表增删就有流畅位移动画。要是用 React,得自己维护 key、用 CSSTransition 或 framer-motion,配置更繁琐。我不是说 React 不好,只是 Vue 在“快速实现精致交互动效”这件事上,对前端友好度拉满。
项目架构:从零搭建一个生产级 Vue3 应用
我这次项目托管在 GitHub 上(私有仓库,别找了 😏),结构如下:
my-docs-app/
├── src/
│ ├── components/ # 通用组件(带动画)
│ ├── views/ # 页面级组件
│ ├── composables/ # 自定义组合函数(如 useDrag, useLocalStorage)
│ ├── services/ # API 请求封装
│ ├── stores/ # Pinia 状态管理
│ └── main.ts
├── public/
├── vite.config.ts
└── package.json
关键技术选型:
| 类别 | 技术栈 | 理由 |
|---|---|---|
| 构建工具 | Vite | 快!快!快! |
| 状态管理 | Pinia | 更简洁的 Store,TypeScript 支持一流 |
| HTTP 客户端 | Axios + interceptors | 统一处理 loading、错误、token |
| 动画 | Vue 内置 Transition + 自定义指令 | 减少第三方依赖 |
| UI 框架 | 无(纯手写 CSS) | 为了精准控制动效细节 |
| 代码规范 | ESLint + Prettier | 强迫症必备 |
特别提一句 Pinia —— 真香!比 Vuex 轻量太多,Store 直接导出函数,不用 modules 嵌套,测试也方便。比如用户状态:
// stores/user.ts
import { defineStore } from 'pinia'
import { api } from '@/services'
export const useUserStore = defineStore('user', () => {
const profile = ref<User | null>(null)
const loading = ref(false)
const fetchProfile = async () => {
loading.value = true
try {
profile.value = await api.get('/user/me')
} finally {
loading.value = false
}
}
return { profile, loading, fetchPrfile }
})
和后端联调:那些让我想砸键盘的时刻
前端再炫酷,没数据也是白搭。我们后端用的是 NestJS(TypeScript 写的,还算友好),但接口文档更新永远慢半拍。最崩溃的一次是上周五晚上 11 点,我做好了一个拖拽排序功能,结果发现后端接口居然不支持 PATCH /docs/order,只接受全量替换!
当时真的想冲进 Slack 问后端兄弟:“你是认真的吗?全量替换怎么保证并发安全?!”
最后妥协方案:前端本地先更新顺序,发个 debounced 请求,等后端下周加接口。这就是现实:再好的前端架构,也扛不住后端 API 设计反人类。
不过我也学乖了:现在每次开工前,先和后端对齐 OpenAPI spec,用 Swagger mock 数据。Vite 的 proxy 也配好了:
// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})
动画实战:让交互相“呼吸”
回到核心需求——丝滑动画。除了 Vue 内置 Transition,我还写了两个自定义指令来增强体验:
v-fade-in:元素进入时淡入 + 微移v-draggable:让任意元素可拖拽(配合useDragcomposable)
比如这个卡片组件:
<template>
<div v-fade-in class="card" v-draggable>
<slot />
</div>
</template>
指令实现(简化版):
// directives/fadeIn.ts
export const fadeIn = {
mounted(el: HTMLElement) {
el.style.opacity = '0'
el.style.transform = 'translateY(10px)'
requestAnimationFrame(() => {
el.style.transition = 'opacity 0.3s, transform 0.3s'
el.style.opacity = '1'
el.style.transform = 'translateY(0)'
})
}
}
浏览器兼容性方面,主要测了 Chrome、Safari 和 Firefox 最新版。Edge 基本和 Chrome 一致。移动端用 iOS Safari 测试过,硬件加速开启后帧率很稳(记得给动画元素加 transform: translateZ(0) 触发 GPU)。
性能优化上,避免在 v-for 里放复杂计算;动画尽量用 transform 和 opacity,不触发布局重排。Chrome DevTools 的 Performance 面板帮我揪出了几个掉帧点——原来是某个 watcher 没加 deep: false,导致每次输入都全量 diff。
GitHub 实践:从提交信息到 CI/CD
虽然是个人项目,但我完全按团队标准来:
- commit message 用 Conventional Commits(feat:, fix:, chore:)
- 分支策略:main + feature branches
- PR 模板强制填写改动点、测试方式
还配了简单的 GitHub Actions,跑 lint + typecheck:
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- run: pnpm install
- run: pnpm lint
- run: pnpm type-check
虽然没上自动化部署(穷学生买不起云服务器 😭),但流程走一遍,对工程化理解深了不少。以后面试被问“你们项目怎么保证代码质量”,总算能说出点东西了。
总结:Vue 生态,不止是框架
折腾完这个项目,我对 Vue 的理解从“会用”变成了“知道怎么用好”。它的生态不是一堆零散工具,而是一个高度协同的体系:Vite 提速开发,Pinia 管理状态,Composition API 组织逻辑,内置 Transition 处理动画——各司其职,又无缝衔接。
当然,我也清楚 Vue 的局限:大型团队协作时,React 的灵活性可能更合适;SSR 场景下 Nuxt 虽强,但 Next.js 社区更大。但对我这种喜欢快速产出、注重交互细节的开发者来说,Vue3 + TS + Vite 的组合拳,真的香。
秋招在即,我不再盲目追新框架,而是把一个技术栈吃透。毕竟,能用 Vue 做出媲美 React 的体验,才是真本事。
对了,如果你也在准备前端秋招,欢迎来我 GitHub 看代码(Star 一下更好哈哈)。深夜写代码的路上,咱们一起卷!

评论 0