从项目结构开始认识 Vue 3
一、为什么先看项目结构
很多初学者学习 Vue 时,会直接从 v-if、v-for 或 ref() 开始背语法。这样可以写出简单示例,却经常无法回答下面的问题:
- Vue 项目从哪个文件启动?
- URL 为什么能够打开一个
.vue页面? views、components、api和router分别放什么?.vue文件是不是全部都要配置路由?.ts文件是不是只保存工具函数?
阅读真实项目时,第一步不是逐行理解代码,而是先找到项目的入口和主要目录。
二、Vue 在前端系统中的位置
一个典型前后端分离系统可以简化为:
text
用户操作浏览器
↓
Vue 负责页面结构、状态和交互
↓
API 模块向后端发送请求
↓
后端返回 JSON 数据
↓
Vue 根据新数据自动更新页面
Vue 主要解决的是浏览器端的问题。它不会替代数据库,也不会直接完成后端业务计算。
在大型数字孪生页面中,Vue 通常负责:
- 展示炉次、设备、风险和预测数据;
- 管理实时模式与历史回放模式;
- 响应按钮、滑块和开关操作;
- 调用后端接口;
- 将数据传递给 Three.js 等第三方模块;
- 在页面退出时停止定时器并释放资源。
三、一个常见的 Vue 3 项目目录
text
project
├─ index.html
├─ package.json
├─ vite.config.ts
└─ src
├─ main.ts
├─ App.vue
├─ router
│ └─ index.ts
├─ views
│ └─ heat
│ └─ twin.vue
├─ components
├─ api
│ ├─ heat.ts
│ └─ types.ts
├─ stores
├─ utils
├─ assets
└─ styles
1. main.ts:应用启动入口
main.ts 通常完成三件事:
ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
这段代码可以理解为:
text
创建 Vue 应用
↓
安装路由系统
↓
把 App.vue 挂载到 index.html 中的 #app
2. App.vue:根组件
App.vue 是整个组件树的根。一个使用 Vue Router 的项目,根组件中经常只有布局和 router-view:
vue
<template>
<router-view />
</template>
router-view 可以理解为一个"页面插槽"。当前 URL 匹配到哪个路由,就把对应页面组件显示在这里。
3. router/index.ts:URL 与页面的映射表
ts
const routes = [
{
path: '/heat/twin',
name: 'HeatTwin',
component: () => import('@/views/heat/twin.vue')
}
];
这表示访问 /heat/twin 时,Router 会加载 twin.vue。
4. views:路由页面
views 通常保存能够对应完整 URL 的页面,例如:
text
views/heat/index.vue
views/heat/detail.vue
views/heat/twin.vue
但这只是一种项目约定,不是 Vue 的强制规则。
5. components:可复用子组件
例如:
text
components/StatusCard.vue
components/WarningList.vue
components/PlaybackToolbar.vue
这些组件一般不会单独对应 URL,而是被页面组件导入和使用。
6. api:接口请求封装
页面中不建议反复编写完整请求地址。通常先在 API 模块中封装:
ts
export function getHeatDetail(heatId: string) {
return request({
url: `/heat/${heatId}`,
method: 'get'
});
}
页面只需要调用:
ts
const { data } = await getHeatDetail(heatId.value);
7. types.ts:接口数据类型
ts
export interface HeatHeaderVO {
heat_id: string;
converter_no: string;
steel_grade: string;
status: string;
}
这类文件帮助 TypeScript 判断接口字段是否正确。
四、.vue 和 .ts 文件分别负责什么
.vue 文件
一个 .vue 文件可能是:
- 路由页面;
- 可复用业务组件;
- 布局组件;
- 图表或三维视口组件。
所以,不是所有 .vue 文件都必须注册到 Router。
.ts 文件
.ts 文件可能保存:
- API 请求函数;
- TypeScript 类型;
- 数据转换函数;
- 业务规则;
- 常量和配置;
- 状态管理;
- Three.js 模型或渲染逻辑。
所以,不能简单地把 .ts 全部理解成"被 Vue 调用的功能文件"。它的职责取决于所在目录和导出内容。
五、大型 Vue 页面应该怎样阅读
面对一个数千行的页面,不建议从第一行一直读到最后一行。可以按照下面的顺序:
第一步:看 <template>
先回答:
- 页面分成哪些区域?
- 有哪些按钮、列表、面板和子组件?
- 哪些内容通过
v-if切换? - 哪些内容通过
v-for生成?
第二步:看 import
根据导入路径判断依赖:
text
@/api/... 后端接口
./twin/... 当前业务模块
three Three.js
vue-router 路由
Element Plus UI 组件
第三步:看 ref 状态
把状态分类:
text
页面状态:loading、sectionError
业务数据:heatMeta、playback、snapshot
交互状态:playbackIndex、displayMode
资源引用:twinCanvasRef、timer
第四步:看 computed
计算属性通常说明"原始数据如何变成页面需要的数据"。
第五步:找数据入口
重点寻找:
ts
loadData()
loadTwinData()
loadSnapshotData()
理解页面从哪里获取数据。
第六步:找生命周期
ts
onMounted(...)
onBeforeUnmount(...)
它们分别说明页面如何启动和如何退出。
第七步:最后看 watch 和辅助函数
这些代码通常负责状态同步、格式化、错误处理和第三方模块更新。
六、把大型页面理解为"总协调器"
真实项目中的大型页面通常不是亲自完成所有算法,而是组合多个模块:
text
twin.vue
├─ 读取路由参数
├─ 调用 API
├─ 保存响应式状态
├─ 计算显示数据
├─ 渲染模板
├─ 调用三维模块
├─ 管理实时轮询
└─ 退出时释放资源
这类文件更接近"页面总控制器"或"页面协调器"。
七、常见误区
误区 1:所有 .vue 都是页面
错误。很多 .vue 是子组件,不会配置独立路由。
误区 2:所有跳转都使用 router.push()
错误。还可以使用:
ts
router.replace();
router.back();
模板中也可以使用:
vue
<router-link to="/heat">炉次中心</router-link>
误区 3:应该先读所有工具函数
大型页面中的辅助函数数量可能很多。先建立页面主链,再按调用关系深入阅读,更有效率。
八、本章小结
阅读 Vue 项目时,先找到:
text
main.ts → App.vue → router → views 页面
阅读大型页面时,先建立:
text
模板结构 → 状态 → 计算属性 → 数据入口 → 生命周期
下一章将进入 .vue 文件内部,系统学习单文件组件和模板语法。