以期提高代码的可读性和可维护性,要求前端代码规范,利用vscode编辑器和eslint代码检查工具可以辅助我们编写符合规范的前端代码,在保存代码时按照eslint配置自动格式化后保存代码
eslint + vscode
- 安装 ESLint 扩展
- 配置vscode设置(用户设置 工作区设置 文件夹设置)以下只列出了 用户设置, 如针对工作区和文件夹有特殊需求可以再自行设置
{
"workbench.startupEditor": "newUntitledFile",
"search.followSymlinks": false,
"editor.tabSize": 2,
"editor.insertSpaces": true,
"editor.fontSize": 18,
"window.zoomLevel": 1,
"files.associations": {
"*.cjson": "jsonc",
"*.wxss": "css",
"*.wxs": "javascript"
},
"emmet.includeLanguages": {
"wxml": "html"
},
"minapp-vscode.disableAutoConfig": true,
"eslint.autoFixOnSave": true
}
复制代码
- 在package.json中安装了eslint的依赖
"eslint": "^4.18.1",
"eslint-config-airbnb": "^16.1.0",
"eslint-loader": "^1.9.0",
"eslint-plugin-babel": "^4.1.2",
"eslint-plugin-import": "^2.9.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
"eslint-plugin-react": "^7.7.0",
复制代码
- 在我们项目跟目录添加.eslintrc.js 文件,用于校验代码,编写eslint相关规则
//off warn error 对应的数字 0 1 2
module.exports = {
parser: "babel-eslint",
extends: [
'airbnb',
],
rules: {
'semi': [2, 'always'], // 每行结束 不加引号(可以自动修复)
'max-len' : [1, 80, 2], // 每行的最长长度
'indent': [2, 2], // 缩进 2 个空格
'quotes': [1, 'single'],
'eqeqeq': 0,
'no-unused-expressions': 0, // 三目和短路求值
'no-nested-ternary': 1, // 警告使用嵌套的三目运算
'no-restricted-globals': 1, // 特定的全局变量
'object-shorthand': 1, // 对象字面量缩写语法
'no-trailing-spaces': 1, // 不允许在语句后存在多余的空格
'no-plusplus': 1, // 一元++和--
'comma-dangle': 2, // 尾随逗号(会自动修复)
'arrow-body-style': [2, "always"], //
'prefer-destructuring': 0, // 不强制使用解构
'import/first': 2, // import 完全写到文件最前面的关系
'object-curly-newline': 0, // 非强制对象大括号和其他令牌内部的换行符
'react/no-array-index-key': 0, //用索引当做key值
'react/no-danger': 1, //直接插入html
// 禁止在使用了 dangerouslySetInnerHTML 的组件内添加 children
'react/no-danger-with-children': 0,
'react/no-string-refs': 1, //直接使用ref属性获取元素
'no-shadow': 2, // 禁止 局部变量与其包含范围内的变量共享相同名称
'no-tabs': 0, // 不允许使用制表符
'no-mixed-spaces-and-tabs': 0, // 允许制表符和空格来缩进
'no-param-reassign': 2, // 赋值给声明为函数参数的变量可能会引起误解
'global-require': 2, // 所有调用require()都位于模块的顶层
'arrow-parens': [2, 'always'], // 禁止箭头函数可以省略括号
'no-console': 1,
'keyword-spacing': [2, { "before": true, 'after': true }], // 关键字前后空格 可以自动修复
'eol-last': [1, 'always'], // 建议尾随换行符
'no-unused-vars': 1, // 消除未使用的变量,函数和函数的参数 自动修复
'space-before-blocks': 2, //块之前的间距一致性
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,
},
"globals":{
"document": true,
"localStorage": true,
"window": true,
"location": true,
}
}
复制代码
更加深入解释说明
- no-unused-expressions
这条规则有两个子规则: 一个是是否允许短路求值(allowShortCircuit) 还有一个是是否允许三目运算符(allowTernary)
所以你在eslint的配置文件里rules规则里面设定下就行了,短路求值和三目运算都允许:
'no-unused-expressions': 0 想要单独禁止某一项,比如下面是允许三目,不允许短路:
'no-unused-expressions': [2, { 'allowShortCircuit': false, 'allowTernary': true }]
- object-shorthand
Here are a few common examples using the ES5 syntax:
// properties
var foo = {
x: x,
y: y,
z: z,
};
// methods
var foo = {
a: function() {},
b: function() {}
};
复制代码
Now here are ES6 equivalents:
/*eslint-env es6*/
// properties
var foo = {x, y, z};
// methods
var foo = {
a() {},
b() {}
};
复制代码
Each of the following properties would warn:
/*eslint object-shorthand: "error"*/
/*eslint-env es6*/
var foo = {
w: function() {},
x: function *() {},
[y]: function() {},
z: z
};
In that case the expected syntax would have been:
/*eslint object-shorthand: "error"*/
/*eslint-env es6*/
var foo = {
w() {},
*x() {},
[y]() {},
z
};
复制代码
- space-before-blocks
此规则将强化块之前的间距一致性。它只适用于不以新行开始的块。
此规则忽略介于=>和块之间的间距。间距由arrow-spacing规则处理。 此规则忽略关键字和块之间的间距。间距由keyword-spacing规则处理。
其他通用规范
Css代码规范
1、每个css属性占用一行,不要在一行罗列属性,例:
.my-class {
width: 100px;
height: 50px;
}
复制代码
2、属性名和属性值都使用小写字母(虽然不区分大小写,但是为了规范还是要全部写成小写)
3、选择器尽量使用类选择器,不要对某一dom下的无意义标签进行样式设置(比如:div、span),无法预知样式影响范围
/* 不推荐 */
.my-class div {
width: 100px;
height: 50px;
}
复制代码
4、属性名和属性值之间要有冒号,属性值后面要有分号,冒号后要有空格(css里的空格位置参考js),选择器前如果有内容需要添加空行
.my-class {
width: 100px;
height: 50px;
}
.next-section {
color: #fff;
}
复制代码
5、0不要添加单位,字符串属性值使用单引号
jsx代码规范
- 组件的命名和引用均使用大写字母开头,每个组件的定义都需要起一个不同的名字,以便出现问题时能快速定位到出问题的组件
class Header extends Component { }
class Footer extends Component { }
复制代码
- 使用组件时,每个自定义的组件标签都要有关闭标签或关闭的斜线
<Header />
<Button>test</Button>
复制代码
- 自定义属性的命名使用驼峰式命名,小写字母开头,不要和html标签的原生属性冲突
<Button onClickTest={} title="test" >test</Button>
复制代码
- 属性值的大括号前后不需要加空格(区别于js,属性值内的对象和js风格相同)
<Component prop={{ key: 'value' }} />
复制代码
- 每个循环生成的dom片段,都需要添加一个唯一的key属性,推荐使用和其绑定的数据中的唯一值作为key,不推荐使用数组的索引,索引和其对应的记录并没有直接的绑定关系
let dataList = [
{ key: 'add', title: '添加' },
{ key: 'edit', title: '编辑' },
{ key: 'delete', title: '删除' }
]
dataList.map(item => {
return <Button key={item.key} >{item.title}</Button>
})
复制代码
-
在render函数中(或某些周期函数)不要改变state的值,造成循环渲染
-
将较为独立的模块抽离,封装成一个独立的组件,保证单个组件不会变的臃肿
-
在进行对象赋值的时候,尽量使用deep copy,避免在传递属性或修改状态时对其他组件产生影响
-
多行的jsx使用' ( ) '包裹
dataList.map(item => {
return (
<div key={item.key} >
<Button>{item.title}</Button>
<span>{item.title}</span>
</div>
)
})
复制代码
- 事件和事件处理函数用on和handle来命名
<Button onClickTest={this.handleClickTest} >test</Button>
复制代码
- 使用函数式组件
function Greeting() {
return <div>Hi there!</div>;
}
<!--从函数参数中获得props-->
function Greeting(props) {
return <div>Hi {props.name}!</div>;
}
复制代码
- 解构props
function Greeting({name}) {
return <div>Hi {name}!</div>;
}
复制代码
- 条件式渲染
// if
{
condition && <span>Rendered when `truthy`</span>;
}
// unless
{
condition || <span>Rendered when `falsy`</span>;
}
// if-else
{
condition ? (
<span>Rendered when `truthy`</span>
) : (
<span>Rendered when `falsy`</span>
);
}
复制代码
参考文档
参考文档1: 腾讯eslint文档
参考文档2: airbnb 规范
参考文档2: eslint文档