Files
telecom-rd-project-template/.agents/skills/telecom-rd-standards/references/source-documents/07-frontend-coding.md
T
2026-07-28 22:30:20 +08:00

19 KiB
Raw Blame History

中国电信软件研发规范编码规范(前端分册)

脱敏整理版:已移除编制人员、联系人和联系方式,并合并无意义硬换行。技术条款、章节和示例以原始 DOCX 为争议核验依据。

中国电信软件研发规范编码规范 (前端分册) (修订版)

中国电信集团有限公司

2023 年 12 月

i

编制人员信息已移除。

版本变更历史

  1. 文档说明

1.1 编制说明

软件行业的高速发展, 对软件开发者的综合素质要求越来越高, 不仅仅是编程知识点,其他维度知识点也会影响最后的交付质量,本文档以开发前端项目角度,详细描写了前端的代码规范,分别从 HTML、CSS、JavaScript、TypeScript、四个方面入手,并且每个章节进行了详细划分,方便读者能快速定位,规范自己的代码, 提高项目代码质量。

1.2 适用范围

本规范适用于指导中国电信软件研发工作。

1.3 起草单位

本规范的起草单位是中国电信集团公司。

1.4 解释权

本规范解释权属于中国电信集团公司。

1.5 版权

本规范的版权属于中国电信集团公司。

1.6 名词解释

  1. 前端研发规范

2.1. HTML 编码规范

2.1.1. 文档类型

  1. 【强制】使用 HTML5 DOCTYPE。

2.1.2. 语言

  1. 【推荐】指定 html 标签上的 lang 属性。

2.1.3. 元数据

  1. 【推荐】使用 UTF-8 字符编码。

声明一个明确的字符编码, 可以让浏览器更快速高效地确定适合网页内容的渲染方式。由于历史原因, 不同浏览器采用了不同的字符编码 。但对于新业务,如无特殊要求, 统一使用 UTF-8 字符编码, 以便统一。在 HTML 中使用 声明文档的编码方式:

  1. 【推荐】页面提供给移动设备使用时, 需要设置 viewport。

2.1.4. 资源加载

  1. 【推荐】引入 CSS 和 JavaScript 时无需指定 type 。 根据 HTML5 规范,引入 CSS 和 JavaScript 时通常不需要指明 type 因为 text/css 和

text/javascript 分别是他们的默认值。

  1. 【推荐】在 head 标签内引入 CSS, 在 body 结束标签前引入 JS。

在 中指定外部样式表和嵌入式样式块可能会导致页面的重排和重绘, 对页面的渲染造成影响 。 因此, 一般情况下, CSS 应在<head></head> 标签里引入。

2.1.5. 页面标题

  1. 【强制】页面需要指定 title 标签, 有且仅有 1 个。

2.1.6. 编码风格

  1. 【推荐】统一使用 2 个空格缩进, 不要使用 4 个空格或 tab 缩进。

  2. 【强制】在 HTML 注释代码中, 不允许出现任何敏感信息。

  3. 【推荐】单行注释, 需在注释内容和注释符之间需留有一个空格, 以增强可读性。

  4. 【推荐】多行注释, 注释符单独占一行, 注释内容 2 个空格缩进。

2.1.7. 标签

  1. 【强制】标签名统一使用小写。

  2. 【推荐】不要省略自闭合标签结尾处的斜线,且斜线前需留有一个空格。

2.1.8. 属性

  1. 【强制】属性值使用双引号, 不要使用单引号。

  2. 【推荐】不要为 Boolean 属性添加取值。

XHTML 需要每个属性声明取值,但是 HTML5 并不需要。一个元素中Boolean 属性存在即表示取值 true, 不存在则表示取值 false

  1. 【推荐】 自定义属性的命名: 以 data- 为前缀。

2.1.9. 语义化

  1. 【参考】尽量根据语义使用 HTML 标签。

2.2. CSS 编码规范

2.2.1. 文件引用

  1. 【强制】一律使用link 的方式调用外部样式。

  2. 【推荐】 不要在 <style> 块中使用 @import 不要在页面中使用 <style> 块。

2.2.2. 命名-组成元素

  1. 【强制】命名必须由字母 、 中划线或数字组成且不能以数字或中划线开头。

  2. 【强制】不允许使用拼音与英文的混合命名, 更不允许直接使用中文的方式; 禁止同一个含义的内容, 在同一个应用中出现多种不同的单词与翻译。

2.2.3. 命名-词汇规范

  1. 【参考】不依据表现形式来命名。

  2. 【参考】可根据内容来命名, 可根据功能来命名。

2.2.4. 命名-缩写

  1. 【强制】保证缩写后还能较为清晰保持原单词所能表述的意思。

  2. 【推荐】使用业界熟知的或者约定俗成的来定义 CSS 类名。

2.2.5. 编码风格

  1. 【强制】所有声明都应该以分号结尾, 不能省略。

  2. 【推荐】使用 2 个空格缩进, 不要使用 4 个空格或 tab 缩进。

  3. 【推荐】选择器和 { 之间保留一个空格。

  4. 【推荐】属性名和 : 之前无空格, : 和属性值之间保留一个空格。

  5. 【推荐】> 、+ 、~ 、|| 等组合器前后各保留一个空格。

  6. 【推荐】在使用 , 分隔的属性值中, , 之后保留一个空格。

  7. 【推荐】注释内容和注释符之间留有一个空格。

  8. 【推荐】声明块的右大括号 } 应单独成行。

  9. 【推荐】属性声明应单独成行。

  10. 【推荐】单行代码最多不要超过 100 个字符。

  11. 【参考】使用多个选择器时, 每个选择器应该单独成行。

  12. 【参考】声明块内只有一条语句时, 也应该写成多行。

  13. 【参考】注释行上方需留有一行空行, 除非上一行是注释或块的顶部。

2.2.6. 选择器

  1. 【参考】不要使用 id 选择器。

id 会带来过高的选择器优先级, 使得后续很难进行样式覆盖(继而引发使用 !important 覆盖样式的恶性循环) 。

  1. 【参考】属性选择器的值始终用双引号包裹。

2.2.7. 属性和属性值

  1. 【推荐】使用尽可能短的十六进制值。

  2. 【推荐】不要使用 !important 重写样式。

  3. 【推荐】十六进制值统一使用小写字母(小写字母更容易分辨) 。

  4. 【推荐】长度值为 0 时, 省略掉长度单位。

  5. 【参考】保留小数点前的 0。

  6. 【参考】属性声明的顺序。

相关联的属性声明最好写成一组, 并按如下顺序排序:

1 定位: 如 position 、left 、right 、top 、bottom 、z-index

2 盒模型: 如 display、float、width、height、margin、padding、border

3 文字排版: 如 font 、color 、line-height 、text-align

4 外观: 如 background

5 其他属性

2.3. JavaScript 编码规范

2.3.1. 对象

  1. 【推荐】使用字面语法来创建对象。

  2. 【推荐】使用对象方法的缩写。

  3. 【推荐】 使用属性值的缩写。

  4. 【参考】避免直接调用 Object.prototype 的方法。

避免直接调用 Object.prototype 的方法, 例如 hasOwnProperty、 propertyIsEnumerable 、isPrototypeOf。这些方法可能会被对象上的属性覆盖, 导致错误。

  1. 【推荐】使用扩展运算符...处理对象,替代 Object.assgin 方法,来进行对象的浅拷贝。

2.3.2. 数组

  1. 【推荐】使用字面语法来创建数组。

  2. 【强制】某些数组方法的回调函数中必须包含 return 语句。

以下数组方法:map, filter, from , every, find, findIndex, reduce, reduceRight, some, sort 的回调函数中必须包含 return 语句, 否则可能会产生误用或错误。一个常见的误用是, 本该用 forEach 的场景却用了 map

  1. 【推荐】使用扩展运算符 ... 处理数组。

ES6 提供了扩展运算符 ..., 可以简化一些数组操作。数组复制:

将类数组结构(有 Iterator 接口的对象)转换为数组:

数组拼接:

用 ... 替代 apply

特殊的,遍历可迭代对象时,使用 Array.from 而不是 ..., 以免创建一个临时数组:

  1. 【推荐】使用解构获取数组元素。

2.3.3. 解构

  1. 【推荐】在访问和使用对象的多个属性的时候使用对象的解构。

  2. 【推荐】对于多个返回值, 推荐使用对象解构而不是数组解构。

2.3.4. 字符

  1. 【强制】使用单引号和反引号定义字符串。

  2. 【推荐】单行最大输入数 100。

  3. 【推荐】文件最大行数 1000。

  4. 【推荐】 函数最大行数 80。

  5. 【推荐】拼接字符串使用模版字符串。

  6. 【推荐】模版字符串可以加入表达式。

2.3.5. 方法

  1. 【强制】永远不要定义一个参数为arguments,这将会优于每个函数给定范围的 arguments 对象。

  2. 【强制】不要用 Function 构造函数创建函数。

使用 new Function 创建函数会像 eval() 方法一样执行字符串,带来安全隐患。

  1. 【强制】不要在块中使用函数声明。

在非函数块(如 if、while 等) 中, 不要使用函数声明:

  1. 【参考】使用函数表达式替代函数声明。

  2. 【强制】不要使用 arguments 对象。

不要使用 arguments 对象, 使用剩余参数操作符 ... 代替。ES6 提供了 rest 操作符 ... 与 arguments 相比可以更清晰地聚合函数的剩余参数 。此外, ... 得到的是一个真正的数组, 而 arguments 得到

的则是类数组结构。

  1. 【推荐】使用默认参数语法。

  2. 【参考】 函数的复杂度不应过高。

圈复杂度不超过 10。认知复杂度不超过 15。

  1. 【强制】将立即执行函数表达式(IIFE) 用小括号包裹。

2.3.6. 箭头函数

  1. 【推荐】 当你需要用匿名函数的时候, 使用箭头函数来替代他。

  2. 【推荐】箭头函数编码风格。

箭头函数参数的小括号 、函数体的大括号在某些时候可以省略,这可能导致风格的不统一, 因此需要规范其编码风格。l 函数体风格当函数体只包含一条 return 语句时, 可以省略函数体大括号和return, 以使代码更简洁。我们推荐使用这个 ES6 提供的语法糖, 它可以让书写和阅读更简洁。但你也可以选择始终加上大括号和 return, 以方便后续在函数体内增加语句。

当 return 的内容为对象或者有多行时, 需要用小括号包裹:

l 函数参数风格当函数只有一个参数, 且函数体为 return 简写语法时, 可以省略包裹参数的小括号以使代码更简洁。

我们建议仅在这种情况下省略包裹参数的小括号,其余情况都不要省略小括号 。但你也可以选择始终加上小括号, 以方便后续可能要增加参数。

2.3.7. 类和构造器

  1. 【推荐】尽量使用 class 来避免操作 prototype。

  2. 【推荐】使用 extends 语句进行类的继承。

extends 是用于原型继承的内建方法, 不会破坏 instanceof。

  1. 【强制】避免不必要的 constructor。

ES6 class 会提供一个默认的 constructor 空 constructor 或者只调用父类的constructor 是不必要的。

2.3.8. 模块

  1. 【推荐】使用 ES6modules 而非其他非标准的模块系统。

  2. 【强制】不要用多个 import 引入同一模块。

  3. 【强制】import 语句需要放到模块的最上方。

  4. 【强制】禁止 default import 的名字跟文件内的其他 export 命名相同。

  5. 【强制】禁止引用自身。

  6. 【强制】禁止循环引用。

  7. 【参考】import 语句的排序。

import 语句建议按以下规则排序:先 import 第三方模块, 再 import 自己工程里的模块先 import 绝对路径, 再 import 相对路径

2.3.9. 迭代器和发生器

  1. 【参考】尽量使用 JavaScript 高阶函数来替代 for-in 和 for-of

需要迭代运算时,应优先使用 JS 提供的高阶函数,减少直接使用 for 循环(包括 for-in 和 for-of 。如使用 map() / every() / filter() / find() / findIndex() / reduce() / some() / ... 来迭代数组, 使用 Object.keys() / Object.values() / Object.entries() 方法来迭

代对象。

  1. 【强制】不要使用发生器, 因为它们不适配es5。

2.3.10. 属性

  1. 【强制】访问属性时使用点符号。

  2. 【强制】访问变量属性时, 使用[]表示法。

2.3.11. 变量

  1. 【强制】使用 const 或者 let 来定义变量,避免因创建全局变量而污染全局命名空间。

2.3.12. 比较运算符和符号

  1. 【强制】使用 === 和 !== 来替代 == 和 !=

非严格相等运算符(== 和 !=)会在比较前将被比较值转换为相同类型,对于不熟悉 JS 语言特性的人来说, 这可能造成不小的隐患。因此,一般情况下我们应该使用严格比较运算符( === 和 !==)进行比较 。如果要比较的两个值类型不同,应该显性地将其转换成相同类型再进行严格比较,而不是依赖于 == 和 != 的隐式类型转换。

  1. 【强制】避免嵌套的三元表达式。

  2. 【强制】避免不必要的三元表达式。

2.3.13. 块

  1. 【推荐】 当有多行代码块的时候, 使用大括号包裹。

  2. 【强制】不要使用空代码块。

  3. 【强制】对于非空代码块, 采用 Egyptian Brackets 风格。

对于非空的代码块, 大括号的换行方式采用 Egyptian Brackets 风格,具体规则如下:左大括号 { 前面不换行, 后面换行右大括号 } 前面换行右大括号 } 后面是否换行有两种情况:如果 } 终结了整个语句, 如条件语句 、函数或类的主体, 则需要换行如果 } 后面存在 else、catch、while 等语句, 或存在逗号、分号、右小括号()), 则不需要换行

2.3.14. 控制语句

  1. 【强制】switch 语句中的 case 需要以 break 结尾。

  2. 【参考】控制语句的嵌套层级不要过深。

控制语句的嵌套层级不要超过 4 级, 否则将难以阅读和维护:

  1. 【强制】for 循环中的计数器应朝着正确方向移动。

当 for 循环中更新子句的计数器朝着错误的方向移动时,循环的终止条件将永远无法达到,这会导致死循环的出现。这时要么是程序出现了错误,要么应将for 循环改为 while 循环。

2.3.15. 注释

  1. 【推荐】使用/**...*/来进行多行注释。

  2. 【推荐】使用 // 进行单行注释。

  3. 【强制】注释内容和注释符之间需要有一个空格。

2.3.16. 代码风格

  1. 【强制】使用 2 个空格缩进。

2.3.17. 逗号

  1. 【强制】逗号不能放在行首。

2.3.18. 分号

  1. 【推荐】添加尾随分号 。。

2.3.19. 命名规范

  1. 【强制】避免单字母的名字 。使用有意义 、能描述功能的名字。

  2. 【参考】文件名: 使用小写字母命名。

考虑到部分操作系统(如 Windows, MacOS) 下文件系统大小写不敏感, 推荐使用 - 连接 。 例如: hello-world.js。

  1. 【参考】使用小驼峰(camelCase) 命名原始类型 、对象 、函数 、实例。

  2. 【强制】使用大驼峰(PascalCase) 命名类和构造函数。

  3. 【参考】命名不要以下划线开头或结尾。

2.3.20. 存取器

  1. 【强制】不要使用 JavaScript 的 getters/setters 方法, 因为它们会导致意外的副作用, 并且更加难以测试 、维护和推敲 。 相应的, 如果你需要存取函数的时候使用 getVal() 和 setVal('hello')。

2.4. TypeScript 编码规范

2.4.1. 代码风格

  1. 【强制】interface/type 类型中使用一致的成员分隔符分号。

  2. 【强制】块开始和结束不能空行。

  3. 【推荐】TS/TSX 在文件中字符串字面量使用单引号或反引号包裹。

  4. 【推荐】 加号 + 连接的两侧同为数字或同为字符串。

数字与字符串的连接往往会导致一些预期外的问题。

  1. 【强制】 即使 if/else/for/while 的语句只有一句, 也不得省略大括号。

  2. 【强制】类型声明时应正确添加空格间距。

TypeScript 类型声明周围添加合适的间距可以有效的提升代码可读性,我们约定:冒号前无空格, 冒号后保留一个空格箭头前后都保留一个空格

  1. 【强制】禁止使用三斜杠语法 /// 导入文件。

三斜杠语法已经被废弃, 声明文件(d.ts) 以外禁止使用。

2.4.2. 类

  1. 【参考】为类成员声明可访问类型。

  2. 【参考】类成员建议以固定的先后顺序排列。

类的静态方法 / 属性(static) 优先于实例的方法 / 属性(instance);属性(field 优先于构造函数(constructor), 优先于方法(method);公开的成员(public 优先于受保护的成员(protected), 优先于私有的成员(private);

  1. 【推荐】如果类的属性是一个字面量, 则推荐使用只读属性 readonly 而不是 getter。

类上所有返回「字面量」的 getter 方法, 都推荐使用 readonly 修饰符来代替, 包括字符串 、数字等。

2.4.3. 接口

  1. 【强制】优先使用 Interface 编写。

  2. 【推荐】接口中的方法使用属性的方式定义。

  3. 【推荐】避免定义空的接口类型。

  4. 【强制】interface 和 type 定义时必须声明成员的类型。

2.4.4. 模块

  1. 【推荐】使用 ES2015 import 语法引入模块。

2.4.5. 重载

  1. 【强制】重载函数写在一起以提高可读性。

2.4.6. 声明

  1. 【推荐】简单数组类型的定义使用 T[], 复杂类型使用 Array。

简单类型(数字、字符串、布尔等)请使用 T[] 或 readonly T[] ,其他复杂类型(联合 、交叉 、对象 、函数等)请使用 Array 或 ReadonlyArray。

  1. 【推荐】初始化为 number/string/boolean 的变量或参数应避免显式的类型声明。

Ts 会主动帮我们推导出类型, 显式声明会导致代码冗余。

  1. 【强制】禁止无意义的 void 类型。

void 类型代表「无」或函数「不返回任何值」, 隐式未定义类型代表函数返回「未定义的值 undefined」, 所以 void 类型无法与除了 never 外的其他类型做联合 、交叉。

2.4.7. 注释

  1. 【推荐】使用 TypeScript 注释指令时需跟随描述说明。

2.4.8. 断言

  1. 【推荐】禁止使用容易混淆的非空断言。

在相等运算符之前增加非空断言容易与不等于混淆, 所以不建议使用。

  1. 【强制】类型断言必须使用 as Type。

2.4.9. 命名空间

  1. 【强制】禁止使用 namespace 来定义命名空间。

自定义 TypeScript 模块(module 和命名空间(namespace) 已经不再推荐使用,首选 ES2015 的模块语法来导入导出。此规则仍然允许定义外部的模块或命名空间。

2.4.10. 变量

  1. 【强制】不得使用 var 声明变量。

  2. 【推荐】只使用const 声明变量,在 const 无法有效涵盖的场景,可按需使用let。

  3. 【推荐】如非必要,不能使用 any 类型标注,使用 any 将会失去 Typescript的类型检查功能 。一般而言, 仅限于与第三方 Javascript 库联合使用, 且无对应定义时可使用 any。

  4. 【参考】一般而言,建议使用 undefined,如非必要,不要使用 null;对于 Vue组件成员初始值,若使用 undefined 可能会导致响应式故障, 可使用初始值代替 。如初始值无意义, 可使用 null。

2.4.11. 枚举

  1. 【参考】使用联合类型替代枚举, 如非必要, 避免在新代码中使用枚举。