Vue3 + TypeScript 企业级规范(通用页面 + 数据大屏 统一+差异化完整版)
前置核心原则(团队必看)
1. 90% 规则全站通用:命名、TS、代码顺序、事件规范、常量抽离、数据流,普通后台页面 / 数据大屏页面 完全统一,保证团队代码风格一致
2. 10% 规则场景差异化:仅组件拆分粒度、生命周期销毁、自适应、样式规则、定时器/图表处理区分普通页 & 大屏页
3. 杜绝两套混乱规范,通用规则统一遵守,差异化规则按需适配
目录
一、全站通用强制规范(所有页面 100% 遵守)
适用于:后台业务页、列表页、表单页、弹窗、大屏模块、大屏页面
1.1 顶级命名规范(统一,无例外)
1)文件 / 组件命名
-
页面/组件:大驼峰 PascalCase → UserListPage、ChartTrend、CommonBox
-
工具/钩子/TS文件:小驼峰 camelCase → useTable、formatTime
-
文件夹:短横线 kebab-case → user-manage、chart-modules
-
CSS类名:短横线 kebab-case → table-wrap、chart-card
2)响应式变量命名(强制后缀/前缀)
-
数组/列表:XXXList → tableList、deviceList、chartDataList
-
业务对象:XXXData / XXXInfo → formData、userInfo、chartData
-
布尔值:is / has 前缀 → isLoading、isVisible、hasData
-
基础变量:语义化小驼峰 → activeTab、pageSize
3)常量规范(全站统一)
-
全局/业务常量、颜色、配置、枚举、固定文案:全大写下划线
-
复用常量统一抽离
src/constants,页面私有少量常量写组件内 -
固定配置强制
as const锁定类型
const CHART_COLORS = ['#1E88E5', '#00C48C'] as const
const STATUS_MAP = { NORMAL: '正常', ERROR: '异常' } as const
4)Props / Emits 规范(全站统一)
-
组件内定义:小驼峰 → chartData、queryParams
-
模板使用:短横线 → :chart-data、:query-params
-
禁止模糊命名:data / info / item
-
自定义事件:短横线命名 → @change-tab、@refresh-data
5)方法/函数 动词前缀规范(全站最核心,统一辨识度)
所有方法必须按前缀分类,禁止随意命名
|
前缀 |
适用场景 |
示例 |
|---|---|---|
|
handle |
所有点击、切换、弹窗、用户交互事件 |
handleTabChange、handleSearch、handleModalOpen |
|
get |
请求接口、获取服务端数据 |
getTableList、getChartData、getUserInfo |
|
submit |
表单提交、数据保存、确认操作 |
submitForm、submitEdit、submitConfig |
|
init |
页面初始化、图表初始化、数据初始加载 |
initPage、initChart、initData |
|
update |
数据更新、图表重绘、局部刷新 |
updateChart、updateTable、updateStatus |
|
reset |
重置表单、重置筛选条件 |
resetForm、resetQuery |
|
destroy/clear |
销毁实例、清除定时器、清空数据 |
destroyChart、clearTimer、clearData |
1.2 全站固定代码顺序(强制统一)
普通页面、大屏页面 脚本顺序完全一致
// 1. Vue 内置API
// 2. 第三方库/工具
// 3. 静态资源/图片
// 4. 组件导入/异步组件
// 5. TS类型导入
// 6. defineProps
// 7. defineEmits
// 8. 常量/配置
// 9. 响应式数据
// 10. 计算属性 computed
// 11. 业务方法(init/get/handle/submit/update)
// 12. 监听 watch
// 13. 生命周期
1.3 全站 TS 强制规范
-
所有
ref必须加明确泛型,禁止隐式 any -
后端赋值必做空值兜底:
val ?? []/val ?? {}/val ?? '' -
Props 必须定义类型 + 默认值
-
禁止全局 any、禁止类型逃逸
-
固定枚举、下拉选项统一
as const锁定类型
1.4 全站数据流规范
-
Props 禁止直接修改,必须同步到本地 ref
-
监听 Props 统一开启
deep: true, immediate: true -
子组件只派发事件,不修改父级数据(单向数据流)
1.5 全站模板 & 样式规范
-
所有组件样式必须加
scoped -
模板禁止行内复杂逻辑,事件统一调用方法
-
条件渲染简写:
v-if="list.length" -
禁止 Math.random() 生成元素ID
二、场景差异化规范(重点:普通页面 VS 大屏页面)
2.1 组件拆分规范差异
普通后台页面(列表/表单/弹窗)
-
拆分原则:复用才抽离,简单页面无需过度拆分
-
单文件允许 300-500 行
-
页面私有组件统一放在当前页面
components文件夹
数据大屏页面
-
拆分原则:模块级强制拆分,一个图表/一个卡片单独组件
-
单文件严格控制 ≤300 行,杜绝巨型页面
-
所有图表、统计卡片、趋势模块全部抽独立组件
2.2 生命周期 & 资源销毁差异
普通后台页面
-
无需特殊销毁,常规数据清空即可
-
无频繁 resize 监听
数据大屏页面(核心差异化)
-
必须监听窗口 resize 自适应
-
页面卸载必须 dispose 销毁echarts实例
-
所有定时器、轮询必须在
onUnmounted清空,杜绝内存泄漏
2.3 常量 & 硬编码差异
普通页面
-
常规状态、枚举抽常量,少量文案可酌情写内联
大屏页面
-
零硬编码强制要求
-
所有颜色、透明度、字体大小、背景图、图表配置、轮播时间全部抽全局常量
2.4 样式差异
普通页面
-
常规固定尺寸、自适应均可
大屏页面
-
根容器必须
width:100%;height:100% -
禁止固定死像素,适配屏幕缩放
-
禁止JS变量与SCSS混用
三、双场景 可直接复制标准模版
3.1 普通后台页面 标准模版(列表/表单页)
<template>
<div class="user-list-page">
<!-- 筛选、表单、表格区域 -->
</div>
</template>
<script setup lang="ts" name="UserListPage">
// 1. Vue API
import { ref, reactive, watch, onMounted } from 'vue'
// 2. 第三方/接口
import { getUserList } from '@/api/userApi'
// 3. 类型
import type { UserItem, UserQueryParams } from '@/types/user'
// 4. 全局常量
import { PAGE_SIZE } from '@/constants/common'
// 5. Props
const props = defineProps<{
status?: number
}>()
// 6. Emits
const emit = defineEmits<{
'row-click': [row: UserItem]
}>()
// 7. 页面私有常量
const STATUS_OPTIONS = [
{ label: '全部', value: 0 },
{ label: '正常', value: 1 },
{ label: '异常', value: 2 }
] as const
// 8. 响应式数据
const loading = ref(false)
const tableList = ref<UserItem[]>([])
const queryParams = reactive<UserQueryParams>({
page: 1,
size: PAGE_SIZE,
status: props.status ?? 0
})
// 9. 业务方法
/** 获取表格数据 */
const getTableList = async () => {
loading.value = true
const res = await getUserList(queryParams)
tableList.value = res.list ?? []
loading.value = false
}
/** 搜索 */
const handleSearch = () => {
queryParams.page = 1
getTableList()
}
/** 重置 */
const resetQuery = () => {
queryParams.page = 1
queryParams.status = 0
getTableList()
}
/** 行点击 */
const handleRowClick = (row: UserItem) => {
emit('row-click', row)
}
// 10. 监听
watch(() => props.status, (val) => {
queryParams.status = val ?? 0
getTableList()
}, { deep: true, immediate: true })
// 11. 生命周期
onMounted(() => {
getTableList()
})
</script>
<style lang="scss" scoped>
.user-list-page {
width: 100%;
padding: 20px;
}
</style>
3.2 数据大屏模块 专属标准模版
<template>
<div class="chart-trend-module">
<common-box title="设备趋势统计">
<div ref="chartRef" class="chart-container"></div>
</common-box>
</div>
</template>
<script setup lang="ts" name="ChartTrendModule">
import { ref, watch, onMounted, onUnmounted } from 'vue'
import * as echarts from 'echarts'
import CommonBox from '@/components/common/CommonBox.vue'
import type { ChartItem } from '@/types/screen'
// Props
const props = defineProps<{
chartData: ChartItem[]
}>()
// Emits
const emit = defineEmits<{
'chart-click': [item: ChartItem]
}>()
// 大屏全局常量
const CHART_COLORS = ['#1E88E5', '#00C48C', '#FFC107'] as const
// 响应式
const chartRef = ref<HTMLElement>()
const chartInstance = ref<echarts.ECharts | null>(null)
const localChartData = ref<ChartItem[]>([])
// 初始化图表
const initChart = () => {
if (!chartRef.value) return
chartInstance.value = echarts.init(chartRef.value)
updateChart()
}
// 更新图表
const updateChart = () => {
if (!chartInstance.value) return
const option = {
color: CHART_COLORS,
tooltip: { trigger: 'axis' },
xAxis: { data: localChartData.value.map(item => item.time) },
series: [{ data: localChartData.value.map(item => item.value), type: 'line' }]
}
chartInstance.value.setOption(option)
}
// 窗口自适应
const handleResize = () => {
chartInstance.value?.resize()
}
// 图表点击
const handleChartClick = () => {
chartInstance.value?.on('click', (params) => {
emit('chart-click', params.data)
})
}
// 监听父组件数据
watch(() => props.chartData, (val) => {
localChartData.value = val ?? []
updateChart()
}, { deep: true, immediate: true })
// 生命周期
onMounted(() => {
initChart()
handleChartClick()
window.addEventListener('resize', handleResize)
})
onUnmounted(() => {
window.removeEventListener('resize', handleResize)
chartInstance.value?.dispose()
})
</script>
<style lang="scss" scoped>
.chart-trend-module {
width: 100%;
height: 100%;
.chart-container {
width: 100%;
height: calc(100% - 36px);
}
}
</style>
四、终极全站速记口诀(通用+差异化)
通用8条(所有页面)
1. 组件大驼峰,变量小驼峰,常量全大写
2. 数组List、对象Data、布尔is前缀
3. 交互handle、请求get、提交submit、重置reset
4. Props小驼峰模板短横线,只读不修改
5. TS必写泛型,赋值必兜底,拒绝any
6. 代码顺序固定分层,不乱序
7. 样式必加scoped,类名语义化
8. 监听必开deep+immediate
大屏专属3条
1、模块强制拆分,单文件精简
2. 零硬编码,所有样式颜色抽常量
3. 必做resize适配、销毁图表、清空定时器
欢迎关注:【前端小知识营地】
更多推荐



所有评论(0)