从“AI写代码?达咩!”到“求求你快帮我修Bug”:我在 Vue 生态里找到的救赎

邓建国
2025-12-13 07:53
阅读 531

“别信 AI,它连 v-model.sync 的区别都搞不清。”
—— 两个月前的我,在茶水间对同事如是说。

那时候刚入职新公司不久,还处在“技术洁癖晚期”阶段。每天打开 VSCode,看着满屏自己一行行敲出来的代码,心里踏实得像刚喝完一杯冰美式。插件装了一堆:Vetur、ESLint、Prettier、Debugger for Chrome……连字体都换了 Monaco,就差在键盘上刻个“手写党永不为奴”。

结果上周五晚上 10 点,产品在群里@我:“这个表单校验逻辑能不能加个动态规则?用户选了‘企业客户’,才显示税号字段,还要实时验证格式……明天上线。”

我盯着屏幕,脑子里已经预演了三套实现方案,手指刚碰到键盘——突然灵光一闪:“等等,我是不是可以用 Vue Use 搞个组合式函数?或者用 Pinia 把校验状态抽出来?”

那一刻我才意识到:我已经彻底沦陷在 Vue 的生态系统里了


被“产品需求”逼进 Vue 生态深水区

说实话,入职这家做 SaaS 平台的公司之前,我对 Vue 的认知还停留在“模板语法 + Options API + Element UI”。毕竟在上一家公司,我们还在用 jQuery 维护一个十年前的老系统(没错,就是那种 <script> 标签直接塞 500 行 JS 的地狱)。

但新团队清一色 Vue 3 + TypeScript + Vite + Pinia + Vue Router 4,CI/CD 跑在 GitLab 上,部署上 K8s,监控用 Prometheus + Grafana。第一天开站会,听见运维小哥轻描淡写地说“那个 Pod CrashLoopBackOff 是因为你的前端镜像没打 tag”,我差点以为自己走错了会议室。

不过真正让我开始认真研究 Vue 生态的,是一次线上事故。

事情发生在上个月底。产品临时加了个“数据看板拖拽排序”功能,我为了赶 deadline,直接 copy 了一段网上找的 SortableJS 封装组件。结果上线后,IE11 用户集体炸锅——不是报错,是整个页面白屏。查了半天才发现,那组件用了 Proxy,而 IE11 连 Promise 都要 polyfill。

当时真的想砸电脑。更惨的是,测试小姐姐幽幽地来了一句:“你们前端能不能别总想着炫技?用户体验比技术栈重要。”

扎心了,老铁。

于是痛定思痛,我决定不再“野路子”开发,而是系统性地摸清 Vue 生态里的那些“真·生产力工具”


工具链:不止是 Vite,还有这些隐藏 MVP

很多人一提 Vue 工具链,张口就是 Vite。确实,Vite 快得离谱,HMR 冷启动不到 500ms,但 Vue 生态的工具远不止于此。下面这几个,是我这两个月用下来觉得“真香”的:

1. Vue DevTools(新版):不只是调试,更是“行为分析仪”

以前用旧版 DevTools,基本只看组件树和状态。但新版(尤其是支持 Vue 3 的版本)简直开了挂:

  • 可以录制组件更新过程,精确到哪个 prop 改变触发了 re-render
  • Pinia store 的时间旅行调试(类似 Redux DevTools)
  • 性能分析面板,直接标出哪些组件 render 太频繁

上周我就靠它揪出一个性能坑:一个列表组件每次父组件更新都会全量 re-render,原因是我把 :key 绑定了数组索引而不是唯一 ID。DevTools 一眼就标红了,改完 FPS 直接从 30 飙到 60。

2. VueUse:300+ 个 Composition Utilities,专治各种“重复造轮子”

比如前面提到的动态表单校验,我原本打算自己写 watch + ref + 正则。结果翻了下 VueUse 文档,发现有个 useVModeluseValidation(配合 vee-validate),三行代码搞定:

// composables/useDynamicForm.ts
import { useVModel } from '@vueuse/core'
import { useField, useForm } from 'vee-validate'

export function useDynamicForm(props: any, emit: any) {
  const customerType = useVModel(props, 'customerType', emit)
  const { validate } = useForm()
  const { value: taxId, errorMessage } = useField('taxId', 
    customerType.value === 'enterprise' ? 'required|taxIdFormat' : ''
  )

  return { customerType, taxId, errorMessage, validate }
}

产品经理看到效果后,眼睛都亮了:“这响应速度,比我点外卖还快!”

3. Unplugin Auto Import:告别 import { ref, computed } from 'vue' 的诅咒

相信我,当你写了 100 个 .vue 文件后,你会对 import { defineProps, defineEmits } from 'vue' 产生 PTSD。现在用 unplugin-auto-import,配置一下就能自动导入:

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'

export default defineConfig({
  plugins: [
    AutoImport({
      imports: ['vue', 'pinia', 'vue-router'],
      dts: 'src/auto-imports.d.ts', // 自动生成类型声明
    })
  ]
})

从此,refcomputeduseStore 直接写,VSCode 还能智能提示。爽到飞起!


状态管理:Pinia 才是 Vue 3 的“天选之子”

还记得刚学 Vue 时被 Vuex 的 mapStatemapActions 绕晕的日子吗?现在有了 Pinia,一切都简单了。

我们项目里有个复杂的审批流程页面,涉及多个步骤的状态同步(草稿保存、提交、撤回、驳回)。以前用 Vuex,store 文件长得像意大利面条。现在用 Pinia,每个模块独立,TypeScript 支持原生,还能直接在组件里解构:

// stores/approval.ts
import { defineStore } from 'pinia'

export const useApprovalStore = defineStore('approval', () => {
  const currentStep = ref(1)
  const formData = reactive({ /* ... */ })
  const isSubmitting = ref(false)

  const submit = async () => {
    isSubmitting.value = true
    try {
      await api.submit(formData)
      currentStep.value++
    } finally {
      isSubmitting.value = false
    }
  }

  return { currentStep, formData, isSubmitting, submit }
})

在组件里直接用:

<script setup>
const { currentStep, submit, isSubmitting } = useApprovalStore()
</script>

<template>
  <button @click="submit" :disabled="isSubmitting">
    {{ isSubmitting ? '提交中...' : '提交' }}
  </button>
</template>

没有命名空间,没有 modules 嵌套,没有神秘的 $store.dispatch。就连我们组那位坚持用 React 的后端转全栈同事都说:“这比 Redux Toolkit 还清爽。”


构建与部署:Vite + Docker + K8s,前端也能玩云原生

作为稍微懂点 K8s 的前端(别笑,我们组就我一个会写 Deployment YAML),我坚持把前端也当成“微服务”来对待。

我们的 CI/CD 流程大概是这样:

  1. git push 触发 GitLab CI
  2. 运行 vite build --outDir dist
  3. 构建 Nginx 镜像(Dockerfile 如下)
  4. 推送到 Harbor 仓库
  5. ArgoCD 自动同步到 K8s 集群
# Dockerfile
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

重点来了:Nginx 配置必须处理前端路由

# nginx.conf
location / {
  try_files $uri $uri/ /index.html;
}

不然刷新页面就 404,运维又要来敲你工位了(别问我怎么知道的)。

另外,Vite 的 base 配置一定要和 Ingress path 对齐:

// vite.config.ts
export default defineConfig({
  base: '/dashboard/', // 对应 K8s Ingress 的 path
})

否则静态资源加载失败,页面一片空白,产品经理又该在群里发“???”了。


性能优化:别让“首屏白屏”毁掉用户体验

Vue 3 本身很快,但不当使用照样卡成 PPT。分享几个实战技巧:

1. 懒加载路由 + 组件

// router/index.ts
const Dashboard = () => import('@/views/Dashboard.vue')

{
  path: '/dashboard',
  component: Dashboard
}

2. v-memo 减少列表重渲染(Vue 3.2+)

<template>
  <div v-for="item in list" :key="item.id" 
       v-memo="[item.id, item.status]">
    <!-- 只有 id 或 status 变化时才更新 -->
  </div>
</template>

3. 图片懒加载 + WebP 格式

我们用 vue-lazyload + CDN 自动转 WebP,首屏图片加载时间从 2.1s 降到 0.7s。


工具对比:我的 VSCode 插件全家桶

插件 作用 吐槽
Volar Vue 3 官方语言支持 别再用 Vetur 了,它已经“退休”了
ESLint + Prettier 代码规范 + 格式化 团队统一配置,避免“空格战争”
REST Client 直接在 VSCode 里调 API 比 Postman 轻量,适合快速测试
Error Lens 错误高亮到行尾 比默认的波浪线下划线直观多了
GitLens 查看每行代码是谁写的 背锅利器(不是)

最后:AI 写代码?真香!

说来惭愧,前几天遇到一个复杂的 ECharts 动态配置问题,死活搞不定。最后实在没招,打开了某 AI 编程助手,输入:“Vue 3 + TypeScript + ECharts,根据 API 数据动态生成多 Y 轴图表”。

它给的代码居然一次跑通!虽然需要手动调整类型定义,但核心逻辑完全正确。那一刻我默默删掉了桌面那张“拒绝 AI”的壁纸。

或许,真正的专业不是排斥工具,而是知道什么时候该用什么工具。Vue 生态给了我强大的武器库,而 AI 成了我的“外挂大脑”。

现在,我依然喜欢手写代码的感觉,但再也不鄙视那些能提升效率的“捷径”了。毕竟——

Deadline 面前,能跑就行;用户体验面前,细节拉满。

共勉。

(PS:本文所有代码均在我司真实项目脱敏后整理,如有雷同,纯属我们都在卷 Vue 😅)

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝