从传统行业转行后,我在杭州用 Vue.js 打怪升级的血泪史

一只会写码的猫
2026-01-04 00:55
阅读 1589

去年夏天,我还在做供应链管理,每天和 Excel、ERP 系统打交道。30 岁那年,实在受不了半夜被叫起来处理“系统卡死”的电话,一咬牙裸辞学编程。三个月啃完 JavaScript 基础,又两个月折腾 Vue,如今在杭州一家中型互联网公司做前端——没错,就是阿里网易扎堆的那片区域。每天听着 Lo-fi Hip Hop 写代码,虽然头发少了点,但至少不用再背锅说“数据不对是 IT 的问题”。

上周五晚上十一点,产品经理突然在钉钉上@我:“这个新功能下周三上线,原型图刚画完,你看看能不能用 Vue 做个动态表单引擎?” 我盯着屏幕,差点把咖啡喷出来。但转念一想:这不正是检验我 Vue 生态掌握程度的好机会吗?


为什么是 Vue?一个“半路出家”者的务实选择

说实话,刚开始学框架时我也纠结过 React 和 Vue。但作为一个从传统行业跳过来的“高龄新人”,时间真的不多。Vue 的文档友好、上手快、社区中文资源多,对我这种没 CS 背景的人来说简直是救命稻草。更重要的是,杭州这边中小企业用 Vue 的比例相当高——毕竟不是每家公司都能养得起 React 专家团队。

而且 Vue 的响应式系统太香了!还记得第一次用 refreactive 实现数据联动时,那种“原来前端也能这么优雅”的震撼感。虽然现在看可能很基础,但对当时的我来说,就像打开了新世界的大门。


项目实战:搞个可配置的动态表单引擎

这次的需求其实挺典型:运营同学需要一个后台,能自己拖拽字段(输入框、下拉框、日期选择器等),保存成模板,然后用户端按模板渲染表单并提交。听起来简单?但细节全是魔鬼。

第一坑:状态管理到底用 Pinia 还是 Vuex?

团队里老哥说:“Vuex 已经过时了,Pinia 才是未来。” 可我翻了下项目历史,发现半年前另一个模块用的是 Vuex,而且没人愿意重构。为了不制造“技术债双胞胎”,我决定统一用 Pinia —— 毕竟 Vue 官方都站队了,而且它的 TypeScript 支持更自然。

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

export const useFormBuilderStore = defineStore('formBuilder', () => {
  const fields = ref<Field[]>([])
  
  const addField = (type: string) => {
    fields.value.push({
      id: Date.now().toString(),
      type,
      label: '',
      required: false,
      options: type === 'select' ? ['选项1', '选项2'] : undefined
    })
  }

  const updateField = (id: string, updates: Partial<Field>) => {
    const field = fields.value.find(f => f.id === id)
    if (field) Object.assign(field, updates)
  }

  return { fields, addField, updateField }
})

小贴士:Pinia 的 setup 风格写法配合 Composition API,逻辑复用比 Vuex 的 modules 清晰太多。尤其适合我这种讨厌写 mapState 的人。


第二坑:组件通信别再 props/$emit 到处乱飞!

表单预览区要实时反映编辑区的改动。一开始我用 v-model + emit,结果嵌套三层后,代码像意大利面条。后来灵机一动:直接把 store 里的 fields 拿来渲染不就行了?

<!-- FormPreview.vue -->
<template>
  <div class="preview">
    <component
      v-for="field in fields"
      :is="getFieldComponent(field.type)"
      :key="field.id"
      :field="field"
    />
  </div>
</template>

<script setup>
import { useFormBuilderStore } from '@/stores/formBuilder'
const { fields } = useFormBuilderStore()
</script>

省去了层层传递,性能还更好——因为 Pinia 的 state 是响应式的,任何修改都会自动触发重渲染。产品经理看到预览区实时同步,眼睛都亮了:“这比上次那个 Java 后台做的快多了!”


第三坑:动态组件 + 异步加载 = 包体积爆炸?

每个字段类型对应一个组件(InputField.vue, SelectField.vue...)。如果全量引入,首屏 JS 会超 500KB。于是祭出 动态导入 + Suspense

// components/FieldComponents.ts
export const fieldMap: Record<string, any> = {
  text: defineAsyncComponent(() => import('./fields/InputField.vue')),
  select: defineAsyncComponent(() => import('./fields/SelectField.vue')),
  date: defineAsyncComponent(() => import('./fields/DateField.vue')),
}

配合 Webpack 的魔法注释还能自定义 chunk 名:

defineAsyncComponent(() => import(/* webpackChunkName: "field-input" */ './fields/InputField.vue'))

最终主包缩小了 40%,Lighthouse 分数从 68 提到 89。运维小哥终于没再吐槽“前端又把 CDN 带宽打满了”。


生态工具链:那些让我少掉 100 根头发的神器

Vite:开发服务器快到飞起

以前用 Webpack,改一行 CSS 要等 3 秒。自从迁移到 Vite,HMR 基本秒级响应。尤其适合我这种喜欢边听《Blinding Lights》Remix 边调试的人——节奏一上来,代码 flow 跟着走。

// vite.config.ts 关键配置
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  },
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          // 分离第三方库
          vendor: ['vue', 'pinia', 'axios'],
          // 分离 UI 库
          ui: ['element-plus']
        }
      }
    }
  }
})

ESLint + Prettier:拯救我的代码洁癖

作为前传统行业从业者,我深知“规范”的重要性。以前写 Excel 公式都要对齐缩进,现在写 JS 更不能乱来。团队强制启用 eslint-plugin-vue,连 template 里的属性顺序都管:

// .eslintrc.json
{
  "extends": ["plugin:vue/vue3-recommended"],
  "rules": {
    "vue/max-attributes-per-line": ["error", { "singleline": 3 }]
  }
}

虽然一开始觉得烦,但当我在凌晨两点排查 bug 时,清晰的代码结构真的救了我。


性能优化:别让 Vue 成为“慢”前端的借口

很多人以为 Vue 自带性能优化,其实不然。我们项目曾因一个列表渲染导致页面卡顿,Chrome DevTools 一开,FPS 掉到 15。

解决方案三板斧:

  1. v-memo 缓存静态节点(Vue 3.2+)

    <div v-for="item in list" :key="item.id" v-memo="[item.id, item.status]">
      <!-- 只有 id 或 status 变化时才更新 -->
    </div>
    
  2. 虚拟滚动:超过 100 条就上 vue-virtual-scroller

  3. 懒加载图片:用 Intersection Observer 自己封装了个 LazyImage 组件

优化手段 首屏加载时间 滚动 FPS
优化前 2.8s 18
仅 Vite 分包 1.9s 25
+ 虚拟滚动 1.7s 52
+ v-memo 1.6s 58

测试妹子跑来问我:“你们前端最近加了什么黑科技?操作丝滑好多!” 其实哪有什么黑科技,不过是把文档里的 best practices 老老实实用了一遍罢了。


云原生时代的前端:K8s 不只是后端的事

作为前传统行业人,我对部署流程特别敏感。以前发个版本要填 5 张审批单,现在我们 CI/CD 流水线跑在 K8s 上,前端构建镜像自动推送到 Harbor,Helm 一键部署。

但有一次,前端镜像太大(1.2GB!),导致 Pod 启动超时。查了半天发现是 node_modules 全打包进去了。后来改成多阶段构建:

# 构建阶段
FROM node:18 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
# 镜像大小从 1.2GB → 28MB!

运维老哥拍我肩膀:“不错啊,前端也开始考虑 infra 了。” 其实我只是不想半夜被 PagerDuty 叫醒而已。


代码人生:30 岁转行,值不值?

经常有人问我:“30 岁学编程是不是太晚了?” 我的回答是:只要别用年龄限制自己,什么时候都不晚

Vue 生态教会我的不仅是技术,更是一种“渐进式”的思维——从小功能做起,逐步迭代,不断优化。这和我之前做供应链优化的思路惊人地相似:先解决最痛的点,再考虑扩展性。

当然,过程肯定狼狈。记得第一次线上事故是因为忘了 key 导致列表渲染错乱,被 QA 围着问了半小时。但正是这些坑,让我从“会写代码”变成“懂工程”。

如今坐在杭州的写字楼里,窗外是西溪湿地,耳机里放着 The Weeknd,手里调着 Element Plus 的主题色。虽然工资还没达到“阿里 P7”的水平,但至少,我在掌控自己的代码人生。


最后几句真心话

如果你也是半路转行的新人,别怕。Vue 的生态足够包容,社区足够温暖。遇到问题先看官方文档(真的,90% 的问题里面都有答案),再搜 GitHub Issues,最后才是 Stack Overflow。

记住:前端不只是切图仔,更是用户体验的守门人。每一个 v-if 的判断、每一个 watch 的监听,背后都是真实用户的等待与期待。

好了,产品又在钉钉上@我改需求了。这次他说:“能不能加个 AI 自动生成表单的功能?” …… 我默默打开了 VS Code,顺手把音乐切到了《Eye of the Tiger》。

(全文完)

评论 0

最热最新
暂无评论
一只会写码的猫Lv.1
0
影响力
0
文章
0
粉丝