目标
本文章作为前端存储库中的良好和不良做法的参考,以便拥有最准确、最有用的参考工具,可以提供最高标准的代码。
参考
GitHub - airbnb/javascript: JavaScript Style Guide是编写干净规范代码的一个很好的起点。下文将在相关情况下引用此资源。
目录
1. Console, Debugging, and Code Comments
2.1 使用模板字面量(Template Literals)连接字符串
3.2 首选 .includes()而不是 .indexOf()=== -1
4.3 命名Boolean Props:isXxx,hasXxx,canXxx
指南
1. Console, Debugging, and Code Comments
1.1 在commit之前移除所有的console
保留console会影响其他开发人员开发其他功能时的console。
// ❌ Bad
function getUser(users) {
console.log(users);
return users.map(({ name }) => name);
}
// ✅ Good
function getUser(users) {
return users.map(({ name }) => name);
}
1.2 在commit之前移除所有的debugger
debugger只能在调试或开发时使用。
// ❌ Bad
function getPerimeter(width, height) {
debugger;
return (width + height) * 2;
}
// ✅ Good
function getPerimeter(width, height) {
return (width + height) * 2;
}
1.3 在commit之前移除所有的注释
未来可能需要或不需要的注释代码会降低代码的可读性。不应提交到源存储库。
如果有一些稍后可能需要的正在进行中的代码,可以将更改存储在新的git分支中或使用git stash将其隐藏起来。
// ❌ Bad
async function getResults(results) {
// const validResults = results.filter(result => result.isValid);
const res = await api.post('/results', results);
if (res.success) handleSuccess(res);
// if (res.error) handleError(res);
}
// ✅ Good
async function getResults(results) {
const res = await api.post('/results', results);
if (res.success) handleSuccess(res);
}
2. Strings
2.1 使用模板字面量(Template Literals)连接字符串
使用模板字面量比用 + 连接更加容易阅读
// ❌ Bad
function introducing(name, class, grade) {
window.alert('My name is ' + name + ', I am in Class ' + class + 'Grade ' + grade + '.');
}
// ✅ Good
function introducing(name, class, grade) {
window.alert(`'My name is ${name}, I'm in Class ${class}, Grade ${grade}.`);
}
GitHub - airbnb/javascript: JavaScript Style Guide 查看更多
3. 运算符和条件
3.1 在比较运算中始终使用严格相等 ===
== 可能不明确。它不为存储在变量中的值提供任何上下文
// ❌ Bad
if (age == 1) {
// ...
}
// ✅ Good
if (age === 1) {
// ...
}
如果对传入类型有任何疑问,请在进行严格的相等比较之前使用显式类型强制:
// ❌ Bad
if (age == '1') {
// ...
}
// ✅ Good
if (Number(age) === 1) {
// ...
}
GitHub - airbnb/javascript: JavaScript Style Guide 查看更多
3.2 首选 .includes()而不是 .indexOf()=== -1
与indexOf()==-1 相比,使用 .includes()可以更简洁地检测数组或字符串中是否存在值。
// ❌ Bad
if (countryOfNames.indexOf('China') === -1) {
// ...
}
// ✅ Good
if (countryOfNames.includes('China')) {
// ...
}
Array.prototype.includes() - JavaScript | MDN
String.prototype.includes() - JavaScript | MDN
查看更多
4. VueJS 规则
4.1 组件和组件文件名
根据Vue文档Single-File Components | Vue.js中的约定,对VueJS组件文件名和脚本中的组件名使用PascalCase
// ❌ Bad
import newComponent from '../../newComponent .vue';
// ❌ Bad
import newComponent from '../../MyComponent.vue';
// ❌ Bad
import NewComponent from '../../newComponent .vue';
// ✅ Good
import NewComponent from '../../NewComponent .vue';
组件不应具有单个单词的名称。这是为了防止与核心HTML元素的命名冲突,因为这些元素总是使用单个单词的名称。
此外,在大多数情况下,多词命名为组件的使用提供了更多的上下文。该规则的对于VueJS入口点,即<App/>组件有很好的可读性。
// ❌ Bad
import Mian from '../../Mian.vue';
import Upload from '../../Upload.vue';
import Header from '../../Header .vue';
// ✅ Good
import UserMian from '../../UserMian.vue';
import ImgUpload from '../../ImgUpload .vue';
import LoginHeader from '../../LoginHeader.vue';
4.2模板中的组件名称
根据Vue文档Component Registration | Vue.js中的建议,在调用模板中的组件时使用PascalCase而不是kebab-case。
// ❌ Bad
<script>
import MyComponent from './MyComponent.vue';
</script>
<template>
<my-component />
</template>
// ✅ Good
<script>
import MyComponent from './MyComponent.vue';
</script>
<template>
<MyComponent />
</template>
4.3 命名Boolean Props:isXxx,hasXxx,canXxx
如果我们使用可预测的命名模式,我们可以为boolean props的含义提供更多的上下文。
为了保持一致性,请尝试遵循以下规则来命名组件上的布boolean
1. 来表示瞬时状态的命名应该像isXxx一样命名
e.g. isOpen, isClose, isDisabled etc.
2. 显示或隐藏UI可选部分的应该像hasXxx一样命名
e.g. hasFooter, hasHeader, hasBorder etc.
3. 与对组件执行某些操作的权限相关的应该像canXxx一样命名
e.g. canEdit, canDelete, canChoose etc.
请注意,上述规则之间可能存在重叠,例如canClose与isClosable与hasCloseButton都可能形成相同的UI。
此外,我们有时可以将多个canXxx权限分组到一个父级isXxx状态下。
// ❌ Bad
<MyComponent
:active="true"
/>
// ✅ Good
<MyComponent
:isActive="true"
/>
// ❌ Bad
<MyComponent
:footer="true"
/>
// ✅ Good
<MyComponent
:hasFooter="true"
/>
// ❌ Bad
<MyComponent
:delete="true"
/>
// ✅ Good
<MyComponent
:canDelete="true"
/>
4.4 VueJS模板中的语义HTML
我们不应该总是在模板中使用div和span,而是应该从HTML标准中选择最合适的元素,并尽可能少地进行定制以获得结果。
HTML和CSS的灵活性使我们能够将任何元素制作成一个UI组件,使其完全按照我们希望的方式运行。但是,因为我们可能会反复使用相同的元素,这会使标记难以理解。我们最终会编写不必要的代码来实现我们可以开箱即用的行为和样式!
如果我们使用语义元素,我们还需要更少的CSS类,因为我们的CSS选择器将有一个清晰的层次结构。在关于CSS类命名的下一节中可以看到更多关于这方面的信息。
语义HTML的好处超出了可维护性和开发人员的经验,可以在以下链接中进一步了解:
2.Semantics - MDN Web Docs Glossary: Definitions of Web-related terms | MDN
3.Semantic HTML: What It Is and How It Improves Your Site
// ❌ Bad
<template>
<div class="component">
<div class="header">
<div class="title">Title</div>
</div>
<div class="main">
<div class="list">
<span class="item">List Item 1</span>
<span class="item">List Item 2</span>
<span class="item">List Item 3</span>
</div>
</div>
<div class="footer">
<span class="button">
Confirm
</span>
</div>
</div>
</template>
// ✅ Good
<template>
<div class="component">
<header>
<h1>Title</h1>
</header>
<main>
<ul>
<li>List Item 1</li>
<li>List Item 1</li>
<li>List Item 2</li>
</ul>
</main>
<footer>
<button>
Confirm
</button>
</footer>
</div>
</template>
4.5 VueJS组件中CSS类的指导原则
如果遵循上面的语义HTML指南,应该能够减少组件中使用的CSS类的数量,并且仍然可以在style中编写干净的CSS代码。
以下是一些使CSS类变得有用和简洁的指南。
1.所有组件都应该有一个与组件名称匹配的根CSS类
2.CSS类应该在脚本顶部的常量中声明
3.修饰符类的命名应类似于is-xxx、has-xxx或can-xxx(遵循第4.3节中boolean props的相同模式)
4.只有在必要的时候,或者当我们需要提高CSS选择器的可读性时,才应该使用CSS类
以下是在实践中显示上述规则的示例组件:
// ✅ Good
// src/components/NewComponent.vue
<script>
const CLASSES = {
BASE: 'new-component',
COLLAPSIBLE: 'collapsible',
MODIFIERS: {
IS_OPEN: 'is-open'
}
};
</script>
<template>
<div :class="CLASSES.BASE">
<header>
<h1>New Component Title</h1>
</header>
<main>
<p>
You can get more information here
</p>
<div :class="[CLASSES.COLLAPSIBLE, { [CLASSES.MODIFIERS.IS_OPEN]: isOpen }]">
// More content here...
</div>
</main>
</div>
</template>
Why?
在文件顶部声明类可以让另一个使用组件的开发人员知道style中需要什么类。如果我们重构一些代码并将其移动到子组件,或者一些代码变得过时,那么这种模式可以很容易地看到style中的冗余内容。
这在大型组件中尤其有用,因为我们可以在文件中的一个位置开始构建对CSS整个范围的简单引用。