【Vue3】day71-vite-setup

作者:mario 发布时间: 2026-09-03 阅读量:4 评论数:0

Day 71 · Vite 项目搭建与大屏骨架迁移 — Vue 版的第一块砖

今天不碰任何图表和数据,只做一件事:把大屏的"壳"用 Vue3 重建——Vite 工程、SFC 单文件组件、三屏容器、scale 自适应壳。壳迁移完成的标准:浏览器打开后,三个屏幕容器按 Day 64 的布局正确摆放(内容暂时空白)、1920×1080 与 1366×768 无破版。壳是所有后续组件的容器,壳不对后面全歪


目录


一、创建工程:Vite + Vue3 + TS

# 在 my-study 下创建 Vue 版大屏工程(与原生版 dashboard 平级)
npm create vue@latest dashboard-vue
# 交互选择:TypeScript = Yes,其余(Router/Pinia/测试)本周先全 No
# —— 生态件 Week 12 再加,今天保持最小心智负担

创建后先跑通:

cd dashboard-vue
npm install
npm run dev        # 打开 http://localhost:5173 看到 Vue 欢迎页
npm run build      # 验证 vue-tsc + vite build 全绿再继续

🎯 npm run build 必须先绿:工程链路有问题时越早暴露越便宜。此后每天收工前 build 一次当回归测试。


二、SFC 与 script setup:心智模型的切换

2.1 从"命令式"到"声明式"

原生版(Day 64-70)的心智:拿 DOM,改 DOM

// 原生版:命令式——状态变了,由你亲手改界面
header.innerHTML = `<span class="tech-card__bar"></span>${title}`;
el.classList.add("screen-hidden");

Vue 版的心智:声明状态,界面是状态的映射

<!-- Vue 版:声明式——只描述"界面长什么样",状态变了界面自动变 -->
<div :class="{ 'screen-hidden': !isActive }"></div>

本周最重要的认知转变:以后你的工作是"改状态",而不是"改界面"。所有 classListinnerHTMLappendChild 手艺,都兑换成"状态 + 模板"。

2.2 SFC 的三段结构

<script setup lang="ts">
// 逻辑:状态、计算、侦听(TS 生效)
import { ref } from "vue";
const title = ref("智慧工厂监控中心");
</script>

<template>
  <!-- 结构:状态的声明式映射 -->
  <header class="screen-header">{{ title }}</header>
</template>

<style scoped>
/* 样式:scoped 让样式只作用于本组件 */
.screen-header { color: var(--text-title); }
</style>

<script setup> 是 Vue3 的语法糖:顶层变量/函数自动暴露给模板,无需 return { title }(选项式 API 的写法,看旧代码时认识即可)。


三、目录设计:Vue 版大屏的骨架

dashboard-vue/
├── server/                  # 直接复用原生版数据服务器(拷贝或软链,一字不改)
├── src/
│   ├── App.vue              # 根组件:scale 壳 + 三屏容器
│   ├── main.ts              # 入口:挂载 + 主题注册
│   ├── styles/
│   │   └── tokens.css       # Day 66 的主题 token 原样搬迁(见第五节)
│   ├── core/                # 与框架无关的纯逻辑(Week 10 迁移过来的类)
│   │   ├── types.ts         # PanelSnapshot / DeviceState 等类型
│   │   └── screen-router.ts # ScreenRouter 暂时原样保留(Week 12 组件化)
│   ├── screens/             # 三屏,每屏一个组件
│   │   ├── ScreenA.vue      # KPI 总览(本周占位)
│   │   ├── ScreenB.vue      # 实时监控(Day 77 的主战场)
│   │   └── ScreenC.vue      # 产线拓扑(Week 13 迁移)
│   └── components/          # 跨屏复用组件(Day 74 开始填充)
└── vite.config.ts

设计原则core/ 放"不 import vue 的代码"(可测试、可迁移),组件层薄薄一层负责"状态 → 界面"。ScreenRouter 本周不组件化——先让旧类在新工程里跑起来,再逐步 Vue 化(绞杀者模式的小型演练)。


四、迁移三屏容器与 scale 壳

4.1 App.vue:scale 壳 + 三屏容器

<script setup lang="ts">
/**
 * 根组件:1920×1080 设计稿 + transform scale 自适应壳
 * 迁移自原生版 Day 55 的 ScaleShell(逻辑一字不改,换成生命周期钩子)
 */
import { onMounted, onUnmounted, ref } from "vue";
import ScreenA from "./screens/ScreenA.vue";
import ScreenB from "./screens/ScreenB.vue";
import ScreenC from "./screens/ScreenC.vue";

const scale = ref(1);           // 缩放系数(响应式,模板自动跟随)

/** 窗口变化时重算缩放(Day 55 原逻辑) */
const updateScale = (): void => {
  scale.value = Math.min(innerWidth / 1920, innerHeight / 1080);
};

onMounted(() => {
  updateScale();
  window.addEventListener("resize", updateScale);   // 成对纪律:挂载注册
});
onUnmounted(() => {
  window.removeEventListener("resize", updateScale); // 卸载清理(Day 69 泄漏教训的 Vue 版)
});
</script>

<template>
  <!-- 外层撑满视口并居中,内层固定设计稿尺寸再整体缩放 -->
  <div class="screen-frame">
    <div class="screen-canvas" :style="{ transform: `scale(${scale})` }">
      <ScreenA />
      <ScreenB />
      <ScreenC />
    </div>
  </div>
</template>

<style scoped>
.screen-frame {
  width: 100vw; height: 100vh; overflow: hidden;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-page);
}
.screen-canvas {
  width: 1920px; height: 1080px; flex: none;   /* 固定设计稿尺寸 */
  transform-origin: center center;
  position: relative;
}
</style>

注意:这里已经悄悄用上了响应式——scaleref,resize 回调里改 scale.value,模板的 transform 自动更新。原生版里"改 style 属性"的活,Vue 版变成"改一个数"

4.2 三屏组件的占位实现

<!-- screens/ScreenB.vue(占位版,Day 77 替换为完整实现) -->
<script setup lang="ts">
/** 屏 B:实时监控(本周从占位开始,逐步长出血肉) */
</script>

<template>
  <section class="screen screen-b">
    <h2>屏 B:实时监控(迁移中)</h2>
  </section>
</template>

<style scoped>
.screen {
  position: absolute; inset: 0;       /* 三屏叠放,互斥显示 */
}
.screen-b { background: var(--bg-page); }
</style>

五、主题 token 的原样搬迁

把原生版 tokens.css(Day 66 的三层 token:raw → 语义 → 组件)整文件复制src/styles/tokens.css,并在 main.ts 引入:

/**
 * 入口:先主题后挂载——保证首帧就有正确配色,避免闪白
 */
import { createApp } from "vue";
import App from "./App.vue";
import "./styles/tokens.css";        // 全局样式不走 scoped,在入口统一引入

createApp(App).mount("#app");

🎯 视觉零变化纪律的落地:token 文件一个字符都不改。改了,"原生 vs Vue 对比"就不成立——对照实验要求控制变量。


六、常见坑点

坑 1:scoped 样式选择不到子组件根元素

scoped 会给选择器加属性后缀,跨组件选中需要 :deep()。规避:全局布局类(.screen 等)放在非 scoped 的全局 CSS 中,组件内 scoped 只写私有样式。

坑 2:Vite 严格模式下水印报错 / vue-tsc 版本不匹配

npm create vue@latest 生成的版本应是自洽的;如果手动升级了 typescript 版本导致 vue-tsc 报错,回退到脚手架版本——第一周不动工具链

坑 3:把 server 也塞进 src 让 Vite 编译

数据服务器是 Node 进程,不归 Vite 管。保持 server/ 独立目录、独立终端启动(node server/index.js),与原生版完全一致——Vue 版前端吃的是同一条数据链路,这本身就是重构正确性的验证手段。

坑 4:模板里忘了 .value(或反过来)

模板中 ref 自动解包(写 scale 不写 scale.value);script 中必须 .value。报错特征:模板显示 [object Object] 或 NaN。建立肌肉记忆:script 里见 ref 名就想 .value,模板里绝不写


七、自测挑战

T1 · 工程搭建 + 骨架迁移(80 分钟)

完成第一至五节:build 绿、双分辨率无破版、三屏占位容器就位、server 复用跑通。

T2 · 响应式初体验(20 分钟)

给 App.vue 加一个当前时间 refsetInterval 每秒更新,onUnmounted 清除定时器),显示在标题栏右侧。体验"改状态 → 界面自动变",并确认卸载后定时器不泄漏(DevTools 里组件树销毁后 CPU 归零)。

T3 · 对照笔记开篇(20 分钟)

新建 NOTES.md,写"原生 vs Vue 对照表"前三行:scale 壳、标题文本、resize 监听——各写两版写法与行数。这个表要维护到 Day 77。


八、总结

环节 要点
工程创建 create-vue 脚手架,TS 开、生态件全关,build 先绿
心智切换 命令式改 DOM → 声明式改状态
目录设计 core/ 不依赖 Vue;screens/ 三屏;旧类先跑再绞杀
scale 壳 逻辑原样迁移,addEventListener 成对清理
主题搬迁 token 整文件复制零修改——对照实验的控制变量

明天进入 Vue 的心脏:响应式系统。

评论