小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
背景
Vue3 + TS 最佳实践 已经给出了组件级别的最佳实践写法,若要指导实践开发,还需要更细粒度的代码规范。 本文脱胎于 Vue3 官网的 风格指南,因为原版内容有点多,而且为了具有更广泛的适应性,原版的标准显然不够“严”。所以本文在分类和严格程度上做了改动,读过此文之后,还是建议把官方文档读一遍,如此良心的文档,不多见了。
正文
以下规范均建立在使用了 Vue3 + TS 最佳实践 的基础之上。
组件(文件)名称
- 所有组件使用
SFC或TSX形式编写; SFC中的标签顺序统一为<script>、<template>、<style>,这样更符合“先声明,后使用”的逻辑,典型案例如下:
<!-- Bad. What is 'routes'? -->
<template>
<div id="nav">
<router-link
v-for="route in routes"
:to="route.path"
:key="route.path"
>
{{ route.name }}
</router-link>
</div>
<router-view />
</template>
<script setup lang="ts">
// It's better to import at top
import { routes } from "./router";
</script>
- 凡是跟组件名相关的(组件名、文件名及在模板中使用),都必须采用大驼峰
PascalCase形式; - 要用多个单词,避免与
HTML(未来)组件冲突; - 一个文件只允许存在一个组件;
- 与父组件紧密耦合的子组件,命名要以父组件名为前缀,例:
TodoList、TodoListItem、TodoListItemButton,详见 紧密耦合的组件名称; - 一般化描述放前,特殊化描述放后,例:
SearchButtonClear、SettingsCheckboxLaunchOnStartup,详见 组件名称中的单词顺序 - 起名尽量使用完整单词而不是缩写,前提是要配置好编辑器,使书写长命名的代价足够低。
属性相关
defineProps、defineEmits要用类型声明的方式,而非运行时声明;- props 声明时使用
camelCase,但在模板中使用时使用kebab-case,详见 Prop 命名 - 一定要为
v-for设置key,且尽量不要用index; v-if和v-for禁止同时出现在一个组件上;- 始终使用指令缩写,即
:、@、#,除了v-bind="obj"这种情况。
其他
- scoped 中尽量避免使用元素选择器,详见 scoped-中的元素选择器;
- 代码中禁止出现
this.$parent、this.$root之类的访问祖先组件的代码,防止数据流混乱; - 使用
hooks代替HOC(高阶组件)和renderProps; hooks、utils、constants、types等文件,就近(尽量深)存放,必要时才做目录提升;- 其他前端普适的、非 Vue 特有的规范,见 Lint 不能解决的前端代码规范;
总结
虽然学习和适应规范有一定的成本,但是统一的规范可以大大降低团队的沟通、维护成本。而且越熟悉业内主流的规范,对于阅读开源项目来说越有利。同样的,自己写的项目满足主流规范,也更容易被他人接受。总之,平时开发时,对于规范的遵守越严格,对未来的好处就越大,当然习惯的成本也会比较大,但这是值得的。
“如闭门造车,出门合辙,了无差异。”——宋·沈作喆《寓卷》七