React 项目中引入 Stylelint 做样式表代码规范

在团队协作开发项目的时候,我们会必不可少的需要写一些 css 样式表。css 虽然不算严格的编程语言,但它在前端开发体系中却占据着重要地位。css 样式表若是写的混乱没有规则,那么对于团队其他成员或后来者或维护者一定是一个令人头痛的问题,尤其是具有代码强迫症的人群。因此写出一手漂亮的,有规则的 css 样式表就显得极为重要。

我们知道在 React 项目中引入 TSLint 做代码规范 这篇文章中介绍了如何使用 TSLint 做代码规范,但 TSLint 并不能对样式表起到代码规范作用。那么在团队协作时如何才能写出统一的规范化的样式表呢?我们知道 Stylelint 是一个强大的、现代化的 CSS 检测工具,它通过定义一系列的编码风格规则帮助我们避免在样式表中出现错误.。本篇文章所要介绍的就是如何在项目中引入 Stylelint 。

注意:本篇文章以 Create React App 项目为例,至于如何创建一个 Create React App 项目请查看 React 项目中引入 TSLint 做代码规范 这篇文章中的步骤1。

步骤1:通过命令安装 stylelint、stylelint-order、stylelint-scss 安装包

a、安装 stylelint:npm install stylelint --save-dev 

b、安装 stylelint-order:npm install stylelint-order --save-dev

c、安装 stylelint-scss:npm install stylelint-scss --save-dev 

注意1:a 中通过命令安装的 stylelint 是使用 Stylelint 做样式表代码规范所需要的一个安装包  ----- 必须安装

注意2:b 中通过命令安装的 stylelint-order 是用来指定样式排序,比如声明的块内(插件包)属性的顺序,例如:先写定位,再写盒模型,再写内容区样式,最后写 CSS3 相关属性 ---- 推荐安装

注意3、c 中通过命令安装的 stylelint-scss 是用来执行各种各样的 SCSS 语法特性检测规则(插件包) ---- 如果是写sass样式表,必须安装,否则不用安装

注意4、除了 b 和 c 这两个插件包,你还可以 点击此处 选择其他你需要的插件包

步骤2:在项目根目录中创建 stylelint.config.js 配置文件

步骤3、根据 配置 | Configuration 中配置 stylelint.config.js 文件中的配置项

stylelint.config.js 文件中是一个大的 json 对象,其中的配置项有:

配置项 rules:规则决定检测器要查找什么和要解决什么

配置项 extends:的值是个“定位器” (或 “定位器” 数组),也是最终被 require() 的,因此,可以使用 Node 的 require.resolve() 算法适应任何格式

配置项 plugins:插件是由社区创建的规则或规则集,支持方法论、工具集,非标准 的 CSS 特性,或非常特定的用例

配置项 processors:Processors 是 stylelint 的钩子函数,可以以它的方式修改代码,也可以在它们退出时修改结果

配置项 ignoreFiles:提供一个 glob 或 globs 数组,忽略特定的文件

步骤4、根据 Rules 中的各个配置项进行配置 stylelint.config.js 文件中的配置项 rules 中的配置项

步骤5、 步骤4中根据 Rules 中配置的配置项是最基本的配置项,此外还要在配置 scss rules 和 order rules

a、因为在步骤1中安装了  stylelint-scss 插件,所以要根据 List of rules 配置相应的 scss rules

b、因为在步骤1中安装了 stylelint-order 插件,所以要根据 stylelint-order 中的 Rules 配置相应的 order rules

步骤6:以 vscode 编辑器为例,需要在 vscode 中安装 stylelint 插件

步骤7、重启编辑器修改样式文件中的声明的块内属性的顺序,查看是否会出现错误警告

备注:我的项目中的 stylelint.config.js 文件 中的配置如下(没有截图,方便拷贝)

module.exports = {

  plugins: [

    'stylelint-scss',

    'stylelint-order'

  ],

  rules: {

    // Possible errors

    'color-no-invalid-hex': true,

    'font-family-no-missing-generic-family-keyword': true,

    'function-calc-no-unspaced-operator': true,

    'function-linear-gradient-no-nonstandard-direction': true,

    'unit-no-unknown': true,

    'property-no-unknown': true,

    'declaration-block-no-duplicate-properties': true,

    'declaration-block-no-shorthand-property-overrides': true,

    'selector-pseudo-class-no-unknown': true,

    'selector-pseudo-element-no-unknown': [

      true,

      {

        ignorePseudoElements: ['ng-deep']

      }

    ],

    'media-feature-name-no-unknown': true,

    'comment-no-empty': true,

    'no-duplicate-at-import-rules': true,

    'no-duplicate-selectors': true,

    'no-empty-source': true,

    'no-extra-semicolons': true,

    'no-invalid-double-slash-comments': true,

    // Limit language features

    'unit-blacklist': [],

    'shorthand-property-no-redundant-values': true,

    'value-no-vendor-prefix': true,

    'property-blacklist': [''],

    'property-no-vendor-prefix': true,

    'declaration-block-no-redundant-longhand-properties': true,

    'declaration-no-important': true,

    'declaration-property-unit-blacklist': {},

    'declaration-property-unit-whitelist': {

      'font-size': ['px', 'rem', 'vmin']

    },

    'declaration-property-value-whitelist': {

      'float': ['none']

    },

    'selector-max-compound-selectors': 4,

    'selector-max-empty-lines': 0,

    'selector-max-id': 1,

    'selector-no-vendor-prefix': true,

    'media-feature-name-no-vendor-prefix': true,

    'at-rule-no-vendor-prefix': true,

    'at-rule-blacklist': ['extend'],

    // Stylistic issues

    'color-hex-case': 'lower',

    'color-hex-length': 'short',

    'font-family-name-quotes': 'always-where-recommended',

    'function-comma-space-after': 'always',

    'function-comma-space-before': 'never',

    'function-name-case': 'lower',

    'function-parentheses-space-inside': 'never',

    'function-url-quotes': 'never',

    'function-whitespace-after': 'always',

    'font-weight-notation': 'numeric',

    'number-leading-zero': 'always',

    'number-no-trailing-zeros': true,

    'string-quotes': [

      'double',

      {

        'avoidEscape': true

      }

    ],

    'length-zero-no-unit': true,

    'unit-case': 'lower',

    'value-keyword-case': [

      'lower',

      {

        ignoreProperties: ['family']

      }

    ],

    'value-list-comma-newline-after': 'always-multi-line',

    'value-list-comma-space-after': 'always-single-line',

    'value-list-comma-space-before': 'never',

    'value-list-max-empty-lines': 0,

    'property-case': 'lower',

    'declaration-bang-space-after': 'never',

    'declaration-bang-space-before': 'always',

    'declaration-colon-space-after': 'always-single-line',

    'declaration-colon-space-before': 'never',

    'declaration-empty-line-before': 'never',

    'declaration-block-single-line-max-declarations': 1,

    'declaration-property-value-blacklist': {

      '/^border/': ['none']

    },

    'block-closing-brace-empty-line-before': 'never',

    'block-closing-brace-newline-before': 'always',

    'block-opening-brace-newline-after': 'always',

    'block-opening-brace-space-before': 'always',

    'selector-attribute-brackets-space-inside': 'never',

    'selector-attribute-operator-space-after': 'never',

    'selector-attribute-operator-space-before': 'never',

    'selector-attribute-quotes': 'always',

    'selector-combinator-space-after': 'always',

    'selector-combinator-space-before': 'always',

    'selector-descendant-combinator-no-non-space': true,

    'selector-pseudo-class-case': 'lower',

    'selector-pseudo-class-parentheses-space-inside': 'never',

    'selector-pseudo-element-case': 'lower',

    'selector-pseudo-element-colon-notation': 'single',

    'selector-type-case': 'lower',

    'selector-list-comma-newline-after': 'always-multi-line',

    'selector-list-comma-space-after': 'always-single-line',

    'selector-list-comma-space-before': 'never',

    'rule-empty-line-before': [

      'always',

      {

        ignore: ['after-comment', 'first-nested']

      }

    ],

    'media-feature-colon-space-after': 'always',

    'media-feature-colon-space-before': 'never',

    'media-feature-name-case': 'lower',

    'media-feature-parentheses-space-inside': 'never',

    'media-feature-range-operator-space-after': 'always',

    'media-feature-range-operator-space-before': 'always',

    'at-rule-empty-line-before': [

      'always',

      {

        ignore: ['after-comment', 'blockless-after-same-name-blockless'],

        except: ['first-nested'],

        ignoreAtRules: ['else']

      }

    ],

    'at-rule-name-space-after': 'always',

    'at-rule-semicolon-space-before': 'never',

    'comment-empty-line-before': [

      'always',

      {

        except: ['first-nested']

      }

    ],

    'comment-whitespace-inside': 'always',

    indentation: 2,

    'max-empty-lines': [

      1,

      {

        ignore: ['comments']

      }

    ],

    'no-eol-whitespace': [

      true,

      {

        ignore: ['empty-lines']

      }

    ],

    // Sass rules

    'scss/at-else-closing-brace-newline-after': 'always-last-in-chain',

    'scss/at-else-closing-brace-space-after': 'always-intermediate',

    'scss/at-else-empty-line-before': 'never',

    'scss/at-else-if-parentheses-space-before': 'always',

    'scss/at-function-named-arguments': 'never',

    'scss/at-function-parentheses-space-before': 'always',

    'scss/at-if-closing-brace-newline-after': 'always-last-in-chain',

    'scss/at-if-closing-brace-space-after': 'always-intermediate',

    'scss/at-mixin-argumentless-call-parentheses': 'always',

    'scss/at-mixin-named-arguments': 'never',

    'scss/at-mixin-parentheses-space-before': 'always',

    'scss/at-rule-no-unknown': true,

    'scss/dollar-variable-colon-newline-after': 'always-multi-line',

    'scss/dollar-variable-colon-space-after': 'always-single-line',

    'scss/dollar-variable-colon-space-before': 'never',

    'scss/dollar-variable-empty-line-before': [

      'always',

      {

        except: ['after-comment', 'after-dollar-variable', 'first-nested']

      }

    ],

    'scss/dollar-variable-no-missing-interpolation': true,

    'scss/dollar-variable-pattern': '^_?[a-z]+[\\w-]*$',

    'scss/at-extend-no-missing-placeholder': true,

    'scss/at-import-no-partial-leading-underscore': true,

    'scss/double-slash-comment-empty-line-before': 'always',

    'scss/double-slash-comment-whitespace-inside': 'always',

    'scss/declaration-nested-properties': 'never',

    'scss/operator-no-newline-after': true,

    'scss/operator-no-newline-before': true,

    // 'scss/operator-no-unspaced': true, // Causing url parsing error, temporarily disabled.

    'scss/selector-no-redundant-nesting-selector': true,

    'scss/no-duplicate-dollar-variables': true,

    // Order rules

    'order/order': [

      'custom-properties',

      'dollar-variables',

      'declarations',

      {

        type: 'at-rule',

        hasBlock: false

      },

      'rules',

      {

        type: 'at-rule',

        hasBlock: true

      }

    ],

    'order/properties-order': [

      [

        'content',

        'position', 'top', 'right', 'bottom', 'left',

        'display', 'flex-flow', 'flex-direction', 'flex-wrap', 'justify-content', 'align-content', 'align-items',

        'flex', 'flex-grow', 'flex-shrink', 'flex-basis', 'align-self', 'order',

        'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',

        'outline', 'outline-width', 'outline-style', 'outline-color', 'outline-offset',

        'box-shadow', 'box-sizing',

        'border-radius', 'border-top-right-radius', 'border-bottom-right-radius', 'border-bottom-left-radius', 'border-top-left-radius',

        'border', 'border-width', 'border-style', 'border-color',

        'border-top', 'border-top-width', 'border-top-style', 'border-top-color',

        'border-right', 'border-right-width', 'border-right-style', 'border-right-color',

        'border-bottom', 'border-bottom-width', 'border-bottom-style', 'border-bottom-color',

        'border-left', 'border-left-width', 'border-left-style', 'border-left-color',

        'border-image', 'border-image-source', 'border-image-slice', 'border-image-width', 'border-image-outset', 'border-image-repeat',

        'padding', 'padding-top', 'padding-right', 'padding-bottom', 'padding-left',

        'max-width', 'max-height', 'min-width', 'min-height', 'width', 'height',

        'background', 'background-attachment', 'background-clip', 'background-origin', 'background-size', 'background-color', 'background-image', 'background-position', 'background-repeat',

        'table-layout', 'border-collapse', 'border-spacing', 'caption-side', 'empty-cells',

        'font', 'font-style', 'font-variant', 'font-weight', 'font-size', 'line-height', 'font-family'

      ],

      {

        unspecified: 'bottom'

      }

    ]

  }

};




参考网址:

stylelint 英文:https://stylelint.io/    

stylelint 中文:https://cloud.tencent.com/developer/chapter/18030

stylelint-order: https://github.com/hudochenkov/stylelint-order

stylelint-scss:https://github.com/kristerkari/stylelint-scss

https://www.cnblogs.com/jiaoshou/p/11284204.html

https://www.cnblogs.com/xiaohuochai/p/9078154.html

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