前端标准

12 阅读13分钟

第一章 技术栈选型

1.1 基础框架 vue / React

1.2样式预编译 less scss/sass

1.3 JavaScript超集 TypeScript

1.4 UI基础框架 Ant Design uni-app(小程序或混合开发)

1.5 服务端渲染 nuxt

第二章 npm版本依赖管理规范

2.1 推荐使用

“^x.x.x”(大版本最新发布的,次一级版本)。

2.2 避免使用

“x.x.x”(锁定版本,只有在新版本和当前重要依赖,有严重冲突才使用)。

2.3 禁止生产环境使用

“*”(任意版本)

“”(任意版本)

“latest”(当前版本)

“file:xxxxx”(本地地址)

“gitxxxxxx”(git地址)

第三章 项目规范

3.1 项目名称 全部采用小写方式, 以中划线分隔

3.2 目录命名 推荐采用小写方式, 以中划线分隔,有复数结构时,要采用复数命名法, 缩写不用复数: scripts / styles / components / images / utils / layouts / demo-styles

3.3 命名严谨性

代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。 说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用:

beijing / huaxia / rmb 等国际通用的名称,可视同英文

3.4 规范化缩写

杜绝完全不规范的缩写,避免望文不知义(尽量不要使用生僻缩写),随意缩写严重降低了代码的可阅读性:

management > mgt / database > DB

3.5 Vue组件命名

项目中组件采用大驼峰命名:

HeadSearch / PageLoading

3.6 Script标签内部结构顺序(推荐)

components > props > data > computed > watch > filter > 钩子函数(钩子函数按其执行顺序) > methods

3.7 Router规范

3.7.1 页面跳转数据传递推荐使用路由参数(推荐)

页面跳转,例如 A 页面跳转到 B 页面,需要将 A 页面的数据传递到 B 页面,推荐使用 路由参数进行传参,而不是将需要传递的数据保存到内存中,然后在 B 页面取出内存的数据,因为如果在 B 页面刷新会导致内存数据丢失,导致 B 页面无法正常显示数据。

3.7.2 使用路由懒加载(延迟加载)机制(推荐)

3.7.3 Router 中的命名规范

path、childrenPoints 命名规范采用kebab-case命名规范(尽量文件的目录结构保持一致,因为目录、文件名都是kebab-case,这样很方便找到对应的文件)。 name 命名规范和component组件名保持一致。

3.8 项目目录规范

3.8.1 命名(推荐)

项目中的所有命名一定要与后端命名统一。 比如认证:后端 auth, 前端无论 router , store, api 等都必须使用 auth 单词。

3.8.2 项目初始化

通过clone模板来初始化项目。可保留备用合并分支。

3.8.3 Router与store目录

router 尽量按照 views 中的结构保持一致。 store 按照业务进行拆分不同的 js 文件。

3.8.4 注意事项

在项目开发中尽量使用框架的数据驱动更新 DOM,尽量(不到万不得已)不要手动操作 DOM,包括:增删改 dom 元素、以及更改样式、添加事件等。 因使用了 git代码版本工具,对于无用代码必须及时删除,例如:一些调试的 console 语句、debugger 语句,无用的弃用功能代码。

第四章 HTML规范

4.1 HTML基础文档 HTML 文件必须加上 DOCTYPE 声明,并统一使用 HTML5 的文档声明,文档编码统一采用UTF-8,注意大小写。

Document

4.2 换行与缩进

缩进用2个空格。 Tab缩进用2个空格代替。 自动换行缩进2个空格。

4.3 元素及标签闭合

所有具有开始标签和结束标签的元素都要写上起止标签,某些允许省略开始标签或和束标签的元素亦都要写上。 空元素标签都不加斜杠 “/”。

某些允许省略开始标签或和束标签的元素亦都要写上


4.4 书写风格

HTML标签名、类名、标签属性和大部分属性值统一用小写。 HTML文本、CDATA、JavaScript、meta标签某些属性等内容可大小写混合。 不需要为 CSS、JS 指定类型属性,HTML5 中默认已包含。 元素属性值使用双引号,不能使用单引号。 特殊字符引用时需要转换为字符实体,如:“<”,“>”,“ ”,需要用&lt;&gt;&nbsp; 替换。更多字符实体


<!--HTML标签名、类名、标签属性和大部分属性值统一用小写-->
<textarea cols="2" data-binding="101" style="width: 100%;"></textarea>
<section></section>

<!--HTML文本、CDATAJavaScript、meta标签某些属性等内容可大小写混合-->
<meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0">
<!--CDATA 内容-->
<script>
<![CDATA[
...
]]>
</script>

<!--不需要为 CSS、JS 指定类型属性,HTML5 中默认已包含-->
<link rel="stylesheet" href="">
<script src=""></script>

<!--写完整的属性-->
<input type="radio" name="name" checked="checked">
<select>
<option value="opt1" selected="selected">Opt1</option>
<option value="opt2">Opt2</option>

4.5 注释

通常采用行注释,内容较多(如模块开头说明信息)时采用多行注释。

<!--
用多行注释:
- 表示内容1。
- 表示内容2.
-->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--以下注释一个自然段落说明-->
<p></p>
</body>
</html>

第五章 CSS规范

5.1 CSS规范

样式文件头部建议加字符编码@charset "UTF-8"。(推荐) 缩进统一用2个空格字符。 每一行申明结束需都要加“;”分号结束,@charset@import必须以“;”分号结束。 开始大括号“{”与选择器在同一行,并与选择间隔1个空格,结束大括号“}”新起一行。 每一行只能申明一个属性和值。 多个选择器使用同一组申明时需要每个将选择器换行。 样式class类名称只能以kebab-case命名。(推荐) 标签选择器最好不能以Id来申明,可直接申明class类名。 带单位值如果为0时,可直接改为0不加单位,如:0px0em0pt,改写为:0

小于1的小数值不能省略0,如:0.45

5.2 CSS预编译器

预编译器的类型跟随系统报采用的主框架UI一致,如:AntD-Vue采用less,element-plus采用scss。

5.3 Less规范

Less基础规范继承CSS规范。 变量定义采用全小写,多个单词用“-”连字符分隔。 计算表达式中运算符前后用空格隔开。 @import "~ant-design-vue/lib/style/color/colors"; // An override for the html selector for theme prefixes @html-selector: html; @normal-color: #d9d9d9; @white: #fff; @width-base: 100px;

.dis { width: @width-base + 10px; }

5.4 Sass规范

Sass基础规范继承CSS规范。 用大括号“{}”代替缩进,采用SCSS风格,禁用SASS缩进风格。 变量定义采用全小写,多个单词用“-”连字符分隔。 计算表达式中运算符前后用空格隔开。

第六章 JavaScript规范

6.1 综述

所有文件类型缩进2个空格(不能使用tab)。 JavaScript/TypeScript统一只用单引号,特殊情况除外。 只能用===作比较,不用==。 不能用var申明变量,改用let,能用const不用let。 不能有console/debugger提交到项目,本地可用。 字符串拼接直接使用反引号【``】。(推荐) 变量函数小驼峰。(推荐) 常量全大写(【_】下划线连接)。(推荐) 类名、构造函数使用大驼峰。 尽量使用箭头函数代替普通函数。 函数参数个数不要超过5个(建议不超过3个,最后一个参数使用Object便于扩展)。(推荐)

第七章 TypeScript规范

7.1 基础类型

numberstringbooleanobject,避免使用NumberStringBooleanObjectenum枚举,常量enum必须使用const定义,枚举项对应值存在多种情况,详情参见更多参考。 any (动态类型)不确定具体类型。 void 类型与 any 类型相反,它表示没有任何类型。 undefinednull 两者各自有自己的类型分别叫做 undefinednullnever类型表示的是那些永不存在的值的类型。

7.2 类型断言

统一使用as语法,JSX.tsx格式只允许asas语法不会导致崩溃,代码保护,全部使用as。

7.3 接口

接口名使用大驼峰形式。 接口属性和方法使用小驼峰,只读属性使用readonly标识。 接口属性或方法必须写注释。 无法确定参数类型的接口方法或属性使用泛型变量: T。 interface IBaseEmployee { // 接口名使用大驼峰形式 // 全名 readonly fullName: T // 接口属性和方法使用小驼峰,只读属性使用readonly标识 /**

  • @name: 改变方式
  • @param {*}name
  • @return {*} */ changeWay(name: T): void } class BaseEmployee extend IBaseEmployee { private fullName: string public changeWay(name: string): void {

} }

7.4 类

类名使用大驼峰形式。 类属性和方法使用小驼峰,属性与方法需加修饰符publicprivateprotect。 类属性一般通过gettersetter 方法来实现数据的封装和有效性校验。 基础类或公共类必须继承于接口。 类属性或方法必须写注释,继承于接口属性或方法除外。 interface IBaseEmployee{ // 全名 readonly fullName: string } class BaseEmployee extend IBaseEmployee { // 类名使用大驼峰形式,基础类继承与接口 private fullName: string // 属性名小驼峰,修饰符private /**

  • @name: 获取姓名
  • @param {*}
  • @return {} / public get fullName(): string { // 属性通过get和set获取和设定 return this.fullName } /
  • @name: 设置姓名
  • @param {*}
  • @return {} / public set fullName(newName: string) { if (passcode && passcode === "hello angular 5") { this.fullName = newName } else { console.log("Error: Unauthorized update of employee!") } } /
  • @name: 改变方式
  • @param {*} name
  • @return {*} */ public changeWay(name: string): void{

} }

为了保证程序的统一,在Windows平台提交git时,需要将 CRLF 转换成 LF,拉取代码时则相反。

7.5 基础组件名

应用特定样式和约定的基础组件 (也就是展示类的、无逻辑的或无状态的组件) 应该全部以一个特定的前缀开头,比如 Base、App 或 V。

这些组件为你的应用奠定了一致的基础样式和行为。它们可能只包括:

HTML 元素 其它基础组件 第三方 UI 组件库 但是它们绝不会包括全局状态 (比如来自 Vuex store)。 它们的名字通常包含所包裹元素的名字 (比如 BaseButton、BaseTable),除非没有现成的对应功能的元素 (比如 BaseIcon)。如果你为特定的上下文构建类似的组件,那它们几乎总会消费这些组件 (比如 BaseButton 可能会用在 ButtonSubmit 上)。 这样做的几个好处: 当你在编辑器中以字母顺序排序时,你的应用的基础组件会全部列在一起,这样更容易识别。 因为组件名应该始终是多个单词,所以这样做可以避免你在包裹简单组件时随意选择前缀 (比如 MyButton、VueButton)。 因为这些组件会被频繁使用,所以你可能想把它们放到全局而不是在各处分别导入它们。使用相同的前缀可以让 webpack 这样工作: var requireComponent = require.context("./src", true, /Base[A-Z]\w+.(vue|js)/) requireComponent.keys().forEach(function (fileName) { var baseComponentConfig = requireComponent(fileName) baseComponentConfig = baseComponentConfig.default || baseComponentConfig var baseComponentName = baseComponentConfig.name || ( fileName .replace(/^.+\//, '') .replace(/\.\w+/, '') ) Vue.component(baseComponentName, baseComponentConfig) })

components/ |- BaseButton.vue |- BaseTable.vue |- BaseIcon.vue

components/ |- AppButton.vue |- AppTable.vue |- AppIcon.vue

components/ |- VButton.vue |- VTable.vue |- VIcon.vue

7.6 紧密耦合的组件名

和父组件紧密耦合的子组件应该以父组件名作为前缀命名。

如果一个组件只在某个父组件的场景下有意义,这层关系应该体现在其名字上。因为编辑器通常会按字母顺序组织文件,所以这样做可以把相关联的文件排在一起。

components/ |- TodoList.vue |- TodoListItem.vue |- TodoListItemButton.vue

components/ |- SearchSidebar.vue |- SearchSidebarNavigation.vue

7.7 自闭合组件

在[单文件组件]、字符串模板和 [JSX] 中没有内容的组件应该是自闭合的——但在 DOM 模板里永远不要这样做。

自闭合组件表示它们不仅没有内容,而且刻意没有内容。其不同之处就好像书上的一页白纸对比贴有“本页有意留白”标签的白纸。而且没有了额外的闭合标签,你的代码也更简洁。 HTML 并不支持自闭合的自定义元素——只有。所以上述策略仅适用于进入 DOM 之前 Vue 的模板编译器能够触达的地方,然后再产出符合 DOM 规范的 HTML。 vue

html

7.8 模板中的组件名大小写

对于绝大多数项目来说,在[单文件组件]和字符串模板中组件名应该总是 PascalCase 的——但是在 DOM 模板中总是 kebab-case 的。

PascalCase 相比 kebab-case 有一些优势:

编辑器可以在模板里自动补全组件名,因为 PascalCase 同样适用于 JavaScript。 视觉上比 更能够和单个单词的 HTML 元素区别开来,因为前者的不同之处有两个大写字母,后者只有一个横线。 如果你在模板中使用任何非 Vue 的自定义元素,比如一个 Web Component,PascalCase 确保了你的 Vue 组件在视觉上仍然是易识别的。 由于 HTML 是大小写不敏感的,在 DOM 模板中必须仍使用 kebab-case。 html

<!-- 在单文件组件和字符串模板中 -->
<MyComponent/>


html
<!-- 在 DOM 模板中 -->
<my-component></my-component>

7.9 JS/JSX 中的组件名大小写

JS/[JSX]中的组件名应该始终是 PascalCase 的。

在 JavaScript 中,PascalCase 是类和构造函数 (本质上任何可以产生多份不同实例的东西) 的命名约定。Vue 组件也有多份实例,所以同样使用 PascalCase 是有意义的。额外的好处是,在 JSX (和模板) 里使用 PascalCase 使得代码的读者更容易分辨 Vue 组件和 HTML 元素。

Vue.component('MyComponent', { // ... })

import MyComponent from './MyComponent.vue'

export default { name: 'MyComponent', // ... }

7.10 完整单词的组件名

组件名应该倾向于完整单词而不是缩写。

编辑器中的自动补全已经让书写长命名的代价非常之低了,而其带来的明确性却是非常宝贵的。不常用的缩写尤其应该避免。

components/ |- StudentDashboardSettings.vue |- UserProfileOptions.vue

7.11 带引号的 attribute 值

非空 HTML attribute 值应该始终带引号 (单引号或双引号,选你 JS 里不用的那个)。

在 HTML 中不带空格的 attribute 值是可以没有引号的,但这鼓励了大家在特征值里不写空格,导致可读性变差。

html
<input type="text">


html
<AppSidebar :style="{ width: sidebarWidth + 'px' }">

7.12 指令缩写

指令缩写 (用 : 表示 v-bind:、用 @ 表示 v-on: 和用 # 表示 v-slot:) 应该要么都用要么都不用。

html
<input
:value="newTodoText"
:placeholder="newTodoInstructions"
>


html
<input
v-bind:value="newTodoText"
v-bind:placeholder="newTodoInstructions"
>


html
<input
@input="onInput"
@focus="onFocus"
>


html
<input
v-on:input="onInput"
v-on:focus="onFocus"
>


html
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>

<template v-slot:footer>
<p>Here's some contact info</p>
</template>


html
<template #header>
<h1>Here might be a page title</h1>
</template>

<template #footer>
<p>Here's some contact info</p>
</template>

第八章 Git规范

8.1 提交日志规范(Git Commit)

代码提交时尽量保证单一功能修改作为一个Commit提交,避免一次提交多个不同文件的不同类功能。

类型 描述 feat 引入新功能 fix 修复 bug style 更新 UI 样式文按键 format 格式化代码 docs 添加/更新文档 perf 提高性能/优化 init 初次提交/初始化项目 test 增加测试代码 refactor 改进代码结构/代码格式 patch 添加重要补丁 file 添加新文件 publish 发布新版本 tag 发布新版本 config 修改配置文件 git 添加或修改.gitignore 文件 chore 改变构建流程、或者增加依赖库、工具等 delete 删除文件

8.2 换行符

CRLF:Windows平台,“\r\n”,换行(LF)和回车(CR) LF:Mac 和 Linux平台,“\n”,回车(CR)