Angular代码风格

写在前面

自身的良好编码风格只能律己,而无法律人;我喜欢 Angular 其中主要一个因素是有一整套的工具风格指南,它可以极大的简化团队开发沟通成本,但是有些小缺失例如在编码风格上官方只提供 TypeScript 的部分,对于其他文件并没有一套指南以及智能化。

VSCode 是我开发 Angular 应用的首选,本文也将以此 IDE 为基准;任何提到的扩展都可以通过市场来获取。

Angular 应用是由组件树组成,一个组件从文件来看包含:TypeScript、HTML、Less(或其他 CSS 预处理器),其中 HTML 可能被包含至 ts 文件里。

当然除此之外还包含一些 JSON 文件、Bash 文件等,当此部分不在本文讨论内。

TSLint

Angular 创建后就已经包含 tslint.json(它是 TSLint 的配置文件),并且所有默认规则都按官方风格指南具体践行。

而 TSLint 的配置文件,默认使用内置预设 tslint:recommended 版本,并在此基础上加入 Angular 质量检查工具 codelyzer,所有这些规则你可以通过 tslint rulescodelyzer 找到每项规则的说明。

规则的写法要么是 boolean 类型,或者使用数组对该规则指定额外参数。

运行 ng lint 命令时,当你某个字符串变量使用双引号,它会提示:

ERROR: /src/app/app.component.ts[9, 16]: " should be '

我们也可以安装 TSLint 扩展让这个触发机制放在正在编码过程中实时反馈:

  1. 当有不符合风格指南会出现一个绿色的波浪线,按 command+. > Fix: " Should be '
  2. 通过终端 PROBLEMS 面板查看所有已打开文件且不符合风格指南的明细

嗯,让你按五次 command+. 快捷键,我一定会疯掉;TSLint 扩展支持在保存文件时自动修复,只需要在项目根目录 .vscode/settings.json 配置:

{
  "editor.codeActionsOnSave": {
    "source.fixAll": true
  }
}

配置

tsline.json 有许多规则是针对任何 TypeScript,而 codelyzer 是专门针对 Angular,以下几个可能你需要认识项:

directive-selectorcomponent-selector

限定 Direcitve、Component 的 selector 选择器属性值的风格,默认必须是 app 开头,有时候对于一些共享型组件设置不同的风格,例如一个业务型富文本框 xx-editor,需要在 tslint.json 修改配置:

"directive-selector": [
  true,
  "attribute",
  ["app", "xx"],
  "camelCase"
],
"component-selector": [
  true,
  "element",
  ["app", "xx"],
  "kebab-case"
]

component-class-suffixdirective-class-suffix

指令或组件类名必须是写驼峰命名法来命名,且必须使用 ComponentDirective 后缀;若团队可能已经习惯类似 View 作为后缀,则:

"component-class-suffix": [true, "Component", "View"],
"directive-class-suffix": [true, "Directive", "View"]

use-life-cycle-interface

强制实现生命周期钩子接口,例如 ngOnInit

export class HeroButtonComponent implements OnInit {
  ngOnInit() {
    console.log('The component is initialized');
  }
}

interface-name

TypeScript 指导原则不建议使用 “I” 前缀;因此建议增加:

"interface-name": [true, "never-prefix"]
// 错误写法
export interface IUser {
  id: number;
}
// 正确写法
export interface User {
  id: number;
}

美化

TSLint 并不支持美化(虽然有几个项看起来像是在“美化”),而美化的工作取决于你采用什么 IDE,例如 VSCode 默认是使用 4 个空格表示一个 Tab 键。

EditorConfig

我不建议依赖 IDE 默认的代码格式配置,所以就有一个 .editorconfig 组织来规范一些简单的统一规范配置。

Angular 项目时也会有 .editorconfig 的配置,虽然有这个配置文件,但在 VSCode 也有自己的一套规范并且优先级更高,所以要想让 EditorConfig 生效需要额外安装 EditorConfig for VS Code 插件。

Editorconfig 只包含一些最基础的项,要想让代码统一风格的美化还是需要更强大的 Prettier。

Prettier

她支持市场上许多语言,其中包含 TypeScript、HTML、Less 这一些都符合 Angular 项目的必备;你需要引入 prettier 以及 VSCode Prettier - Code formatter 扩展。

配置

在根目录下创建 .prettierrc 配置文件以及 .prettierignore 忽略美化配置文件;Editorconfig 选项与 Prettier 选项高度重叠,并且后者会强制替换前者,例如:

# .editorconfig
indent_size = 4
# .prettierrc
{
  "tabWidth": 2
}

表示一个 Tab 宽度使用 2 个空格;我个人建议 Prettier 不应该覆盖 EditorConfig 的部分,它们包含:tabWidthuseTabsendOfLine

而一个简单的 Prettier 配置差不多这样:

{
  // 单行最大长度
  "printWidth": 140,
  // 语句末尾添加分号
  "semi": true,
  // 使用单引号而非双引号
  "singleQuote": true,
  // 尾逗号
  "trailingComma": "all"
}

如果你想忽略一些不想美化的文件,例如 Markdown,则 . prettierignore

*.md

同样如果你期望每次保存文件时自动美化代码,只需要在项目根目录 .vscode/settings.json 配置:

{
  "editor.formatOnSave": true
}

Prettier 与 TSLint

Prettier 配置 项会有部分与 tslint.json 项重复,例如:Prettier 的 printWidthtsline.jsonmax-line-length,对于 Prettier 以她为优先,反之使用 ng lint 会以 tslint.json 优先。

这对我们来说有些困惑,TSLint 包含了一些代码”美化性"(例如:max-line-length),事实上,这更应该是 Prettier 的专长(所有配置都跟代码美化相关)。

tslint-config-prettier

好在 tslint-config-prettier 帮助清理这些可能会产生冲突规则的解决方案:

"extends": [
  "tslint:recommended",
  "tslint-config-prettier"
]

prettier 提供一种检查机制:

tslint-config-prettier-check ./tslint.json

你会发现默认的 Angular 项目中会有 max-line-lengthobject-literal-key-quotesquotemark 三项是冲突的,我们可以关掉 tsline.json 这三项的配置,让 Prettier 来代替。

{
  "rules": {
    "max-line-length": [false, 140],
    "object-literal-key-quotes": [false, "as-needed"],
    "quotemark": [false, "single"]
  }
}

HTML

Prettier 默认会自动识别 Angular 项目并使用其引擎,当然也包含对 templatetemplateUrl 两种写法。

printWidth

会决定一段 HTML 超出长度范围后属性会自动换行:

<h1 style="color: #f50;" data-long="long" data-long-long="long" data-long-long-long="long" data-long-long-long-long="long">
  Share Component
</h1>

变成:

<h1
  style="color: #f50;"
  data-long="long"
  data-long-long="long"
  data-long-long-long="long"
  data-long-long-long-long="long"
>
  Share Component
</h1>

htmlWhitespaceSensitivity

空白敏感这一点同 Angular 的 preserveWhitespaces 类似,如果你的 Angular 项目配置了 preserveWhitespaces: false 则无须理会;反之设定不同的参数会影响美化的效果,若项目对空白敏感有需求可以设定为 strict 会强制清除空白,例如:

<h1
  style="color: #f50;"
  data-long="long"
  data-long-long="long"
  data-long-long-long="long"
  data-long-long-long-long="long"
  >Share Component</h1
>

Less

不管哪种 CSS 预处理器都可以使用 stylelint 作为代码检查工具,安装 stylelintstylelint-config-standard 并在根目录 .stylelintrc 配置:

{
  "extends": [ "stylelint-config-standard" ],
  "plugins": [ ],
  "rules": { },
  "ignoreFiles": [ "src/assets/**/*" ]
}

package.json 定义一条:

{
  "scripts": {
    "lint:style": "stylelint 'src/**/*.less' --syntax less"
  }
}

若缺少 ; 会被收到 Missed semicolon 错误:

:host {
  width: 100px;
  height: 100px
  display: block;
}
src/app/app.component.less
 3:11  ✖  Missed semicolon   CssSyntaxError

stylelint 有自己的一套规则,而 stylelint-config-standard 只是官方提供一种默认规则

Prettier

前面提到 Prettier 也支持 Less,需要额外安装依赖包 prettier-stylelint ,并修改 .stylelintrc 配置:

{
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-prettier"
  ],
  "plugins": [ ],
  "rules": {
    "selector-type-no-unknown": [
      true,
      {
        "ignoreTypes": [
          "/^app-/"
        ]
      }
    ],
    "selector-pseudo-element-no-unknown": [
      true,
      {
        "ignorePseudoElements": [
          "ng-deep"
        ]
      }
    ]
  },
  "ignoreFiles": [ "src/assets/**/*" ]
}

但是依然无法生效,由于在 VSCode 下面 EditorConfig for VS Code 扩展默认并没有开启它,在 .vscode/settings.json 增加:

{
  "prettier.stylelintIntegration": true
}

加上之前已经开启保存时自动修复功能,同样也适用 Less 即保存时根据 .stylelintrc 配置修复及美化。

一些有趣的插件

stylelint-config-rational-order

Css 语言同一类型的相关属性可能会很多,而将这些相关属性进行分组对于维护非常有帮助,安装 stylelint-orderstylelint-config-rational-order,并修改 .stylelintrc 配置:

{
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-rational-order",
    "stylelint-config-prettier"
  ],
  "plugins": [
    "stylelint-order"
  ],
  "rules": { },
  "ignoreFiles": [ "src/assets/**/*" ]
}

stylelint-declaration-block-no-ignored-properties

当设置 display: inline 内联时,此时再写 width: 100px 是无意义的,而该组件可以自动移除这种无效属性。

{
  "plugins": [
    "stylelint-declaration-block-no-ignored-properties"
  ],
  "rules": {
    "plugin/declaration-block-no-ignored-properties": true,
  }
}

智能点

至此,涉及 Angular 所需要的代码风格运用已全部完结,这些检查我们都大多数是依靠 VSCode 编辑器的扩展辅助完成。

事实上,我们只需要增加几个命令来对整个项目进行检查,确保整个项目的代码能按所配置的风格执行。

命令行

{
  "scripts": {
    "lint": "npm run lint:ts && npm run lint:style",
    "lint:ts": "tslint -p tsconfig.app.json -c tslint.json 'src/**/*.ts' --fix",
    "lint:style": "stylelint 'src/**/*.less' --syntax less --fix"
  }
}

tslintstylelint 命令行对应的参数说明,都可以通过上述提供官网找得到。

运行 npm run lint 可以对整个项目进行检查及修复;若有包含 CI 可以直接使用它。

Git

如果可以将这一过程在向源码仓库提交代码时进行检查的话,可以在向代码仓储提交前就发现问题,需要安装 huskylint-staged,并且修改 package.json

{
  "lint-staged": {
    "src/**/*.ts": [
      "npm run lint:ts",
      "git add"
    ],
    "src/**/*.less": [
      "npm run lint:style",
      "git add"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  }
}

当向源码仓库 Commit 时会自动先执行命令行才会 git add

总结

当我写完最后一节时,Angular8 发布了正式版;所以我把原本准备的样板项目 ng-code-style-boilerplatef526a0c) 切换成 Angular8,但完全适用 Angular7.x 版本。

Angular 风格指南中文版)对于喜爱 Angular 是必读、常读的文章,它指引团队更友好的编写代码,个人良好编码风格可能律己,但无法律人,而这种风格指南可以减少无差别的团队沟通。

本文虽然以 Angular 的角度出发,但大部分内容同样适用 React、Vue 等。

(完)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容