前端代碼規範(es6,eslint,vue)

前端開發規範

1、HTML

1.語義化標籤

HTML5 提供了不少語義化元素,更好地幫助描述內容。但願你能從這些豐富的標籤庫中受益。

<!-- bad -->
<div id="main">
  <div class="article">
    <div class="header">
      <h1>Blog post</h1>
      <p>Published: <span>21st Feb, 2015</span></p>
    </div>
    <p></p>
  </div>
</div>
<!-- good -->
<main>
  <article>
    <header>
      <h1>Blog post</h1>
      <p>Published: <time datetime="2015-02-21">21st Feb, 2015</time></p>
    </header>
    <p></p>
  </article>
</main>

image image

請確保正確使用語義化的標籤,錯誤的用法甚至不如保守的用法。

<!-- bad -->
<h1>
  <figure>
    <img alt=Company src=logo.png>
  </figure>
</h1>

<!-- good -->
<h1>
  <img alt=Company src=logo.png>
</h1>

簡潔

確保代碼簡潔,不要再採用XHTML的舊作法。

<!-- bad -->
<!doctype html>
<html lang=en>
  <head>
    <meta http-equiv=Content-Type content="text/html; charset=utf-8" />
    <title>Contact</title>
    <link rel=stylesheet href=style.css type=text/css />
  </head>
  <body>
    <h1>Contact me</h1>
    <label>
      Email address:
      <input type=email placeholder=you@email.com required=required />
    </label>
    <script src=main.js type=text/javascript></script>
  </body>
</html>
<!-- good -->
<!doctype html>
<html lang=en>
  <meta charset=utf-8>
  <title>Contact</title>
  <link rel=stylesheet href=style.css>

  <h1>Contact me</h1>
  <label>
    Email address:
    <input type=email placeholder=you@email.com required>
  </label>
  <script src=main.js></script>
</html>

HTML5 doctype

爲每一個 HTML 頁面的第一行添加標準模式(standard mode)的聲明,這樣可以確保在每一個瀏覽器中擁有一致的展示。javascript

<!DOCTYPE html>
<html>
  <head>
  </head>
</html>

語言屬性

根據 HTML5 規範:css

強烈建議爲 html 根元素指定 lang 屬性,從而爲文檔設置正確的語言。這將有助於語音合成工具肯定其所應該採用的發音,有助於翻譯工具肯定其翻譯時所應遵照的規則等等。

更多關於 lang 屬性的知識能夠從 此規範 中瞭解。html

這裏列出了語言代碼表前端

<html lang="en">
  <!-- ... -->
</html>

IE 兼容模式

IE 支持經過特定的 <meta> 標籤來肯定繪製當前頁面所應該採用的 IE 版本。除非有強烈的特殊需求,不然最好是設置爲 edge mode,從而通知 IE 採用其所支持的最新的模式。vue

閱讀這篇 stack overflow 上的文章能夠得到更多有用的信息。java

<meta http-equiv="X-UA-Compatible" content="IE=Edge">

字符編碼

經過明確聲明字符編碼,可以確保瀏覽器快速並容易的判斷頁面內容的渲染方式。這樣作的好處是,能夠避免在 HTML 中使用字符實體標記(character entity),從而所有與文檔編碼一致(通常採用 UTF-8 編碼)。node

<head>
  <meta charset="UTF-8">
</head>

可用性

可用性不該該是過後才考慮的事情。你能夠經過簡單的修改作出不錯的效果,例如:git

  • 正確使用alt屬性
  • 確保連接和按鈕正確使用(不要用<div class=button>這種粗暴的作法)
  • 不依賴於顏色來傳達信息
  • 給表單作好lable標記
<!-- bad -->
    <h1><img alt="Logo" src="logo.png"></h1>

    <!-- good -->
    <h1><img alt="My Company, Inc." src="logo.png"></h1>

性能

除非有非要在加載內容前加載腳本的必要性由,否則別這樣作,這樣會阻礙網頁渲染。若是你的樣式表很大,必須獨立放到一個文件裏。兩次HTTP 請求不會顯著下降性能。

<!-- bad -->
<!doctype html>
<meta charset=utf-8>
<script src=analytics.js></script>
<title>Hello, world.</title>
<p>...</p>

<!-- good -->
<!doctype html>
<meta charset=utf-8>
<title>Hello, world.</title>
<p>...</p>
<script src=analytics.js></script>

屬性順序

HTML 屬性應該按照特定的順序出現以保證易讀性。

id class name data-xxx src, for, type, href title, alt aria-xxx, role value style

2、CSS

分號

不能漏寫分號

/* bad */
div {
  color: red
}

/* good */
div {
  color: red;
}

儘可能不要改變元素默認行爲。保持默認的文本流。好比,移出一個圖片下面的一個白塊,不影響本來的顯示:

/* bad */
img {
  display: block;
}

/* good */
img {
  vertical-align: middle;
}

相似的,儘可能不要改變浮動方式。

/* bad */
div {
  width: 100px;
  position: absolute;
  right: 0;
}

/* good */
div {
  width: 100px;
  margin-left: auto;
}

選擇器

緊密耦合DOM選擇器,三個層級以上建議加class:

/* bad */
div:first-of-type :last-child > p ~ *

/* good */
div:first-of-type .info

避免沒必要要的寫法:

/* bad */
img[src$=svg], ul > li:first-child {
  opacity: 0;
}

/* good */
[src$=svg], ul > :first-child {
  opacity: 0;
}

指明

不要讓代碼難於重寫,讓選擇器更精確,減小ID、避免使用!important

/* bad */
.bar {
  color: green !important;
}
.foo {
  color: red;
}

/* good */
.foo.bar {
  color: green;
}
.foo {
  color: red;
}

覆蓋

覆蓋樣式會使維護和調試更困難,因此要儘可能避免。

/* bad */
li {
  visibility: hidden;
}
li:first-child {
  visibility: visible;
}

/* good */
li + li {
  visibility: hidden;
}

繼承

不要把可繼承的樣式重複聲明:

/* bad */
div h1, div p {
  text-shadow: 0 1px 0 #fff;
}

/* good */
div {
  text-shadow: 0 1px 0 #fff;
}

簡潔性

保持代碼的簡潔。使用屬性縮寫。沒必要要的值不用寫。

/* bad */
div {
  transition: all 1s;
  top: 50%;
  margin-top: -10px;
  padding-top: 5px;
  padding-right: 10px;
  padding-bottom: 20px;
  padding-left: 10px;
}

/* good */
div {
  transition: 1s;
  top: calc(50% - 10px);
  padding: 5px 10px 20px;
}

語言

能用英文的時候不用數字。

/* bad */
:nth-child(2n + 1) {
  transform: rotate(360deg);
}

/* good */
:nth-child(odd) {
  transform: rotate(1turn);
}

動畫

除了變形和改變透明度用animation,其餘儘可能使用transition。

/* bad */
div:hover {
  animation: move 1s forwards;
}
@keyframes move {
  100% {
    margin-left: 100px;
  }
}

/* good */
div:hover {
  transition: 1s;
  transform: translateX(100px);
}

單位

能夠不用單位時就不用。建議用rem。時間單位用s比ms好。

/* bad */
div {
  margin: 0px;
  font-size: .9em;
  line-height: 22px;
  transition: 500ms;
}

/* good */
div {
  margin: 0;
  font-size: .9rem;
  line-height: 1.5;
  transition: .5s;
}

顏色

須要作透明效果是用rgba,不然都用16進製表示:

/* bad */
div {
  color: hsl(103, 54%, 43%);
}

/* good */
div {
  color: #5a3;
}

繪圖

減小HTTPS請求,儘可能用CSS繪圖替代圖片:

/* bad */
div::before {
  content: url(white-circle.svg);
}

/* good */
div::before {
  content: "";
  display: block;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #fff;
}

註釋

/* bad */
div {
  // position: relative;
  transform: translateZ(0);
}

/* good */
div {
  /* position: relative; */
  will-change: transform;
}

語法

  • 用兩個空格來代替製表符(tab) -- 這是惟一能保證在全部環境下得到一致展示的方法。
  • 爲選擇器分組時,將單獨的選擇器單獨放在一行。
  • 爲了代碼的易讀性,在每一個聲明塊的左花括號前添加一個空格。
  • 聲明塊的右花括號應當單獨成行。
  • 每條聲明語句的 : 後應該插入一個空格。
  • 爲了得到更準確的錯誤報告,每條聲明都應該獨佔一行。
  • 全部聲明語句都應當以分號結尾。最後一條聲明語句後面的分號是可選的,可是,若是省略這個分號,你的代碼可能更易出錯。
  • 對於以逗號分隔的屬性值,每一個逗號後面都應該插入一個空格(例如,box-shadow)。
  • 不要在 rgb()、rgba()、hsl()、hsla() 或 rect() 值的內部的逗號後面插入空格。這樣利於從多個屬性值(既加逗號也加空格)中區分多個顏色值(只加逗號,不加空格)。
/* Bad CSS */
.selector, .selector-secondary, .selector[type=text] {
  padding:15px;
  margin:0px 0px 15px;
  background-color:rgba(0, 0, 0, 0.5);
  box-shadow:0px 1px 2px #CCC,inset 0 1px 0 #FFFFFF
}

/* Good CSS */
.selector,
.selector-secondary,
.selector[type="text"] {
  padding: 15px;
  margin-bottom: 15px;
  background-color: rgba(0,0,0,.5);
  box-shadow: 0 1px 2px #ccc, inset 0 1px 0 #fff;
}

id及class命名

*class應以功能過內容命名,不以表現形式命名,通用且有意義的詞es6

*class與id單詞字母小寫,多個單詞組成時,使用中劃線「-」分隔github

激活及hover的效果class

使用on做爲激活狀態的class,使用hover做爲移上元素(hover)的class

樣式的聲明順序

一、定位

二、盒模型

三、關於文字

四、關於顏色,背景

五、其餘,如:cursor:pointer

.declaration-order {

  /*定位 */

  position: absolute;

  top: 0;

  right: 0;

  bottom: 0;

  left: 0;

  z-index: 100;

  /* 盒模型 */

  display: block;

  box-sizing: border-box;

  width: 100px;

  height: 100px;

  padding: 10px;

  border: 1px solid #e5e5e5;

  border-radius: 3px;

  margin: 10px;

  float: right;

  overflow: hidden;

  /* 關於文字 */

  font: normal 13px "Helvetica Neue", sans-serif;

  line-height: 1.5;

  text-align: center;

  /* 關於顏色,背景 */

  background-color: #f5f5f5;

  color: #fff;

  opacity: .8;

  /*其餘 */

  cursor: pointer;

}

less語法規範

1.變量,混合的使用

變量,混合,容許咱們單獨定義一系列通用的樣式,而後在須要的時候去調用。因此一些公共的樣式規則能夠單獨在一個less文件中定義,其餘地方調用,在作全局樣式調整時能很方便的修改

// LESS

@color: #4D926F;

#header {
  color: @color;
}
h2 {
  color: @color;
}

/* 生成的 CSS */

#header {
  color: #4D926F;
}
h2 {
  color: #4D926F;
}

  //LESS
.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

#menu a {
  color: #111;
  .bordered;
}
.post a {
  color: red;
  .bordered;
}

/* 生成的 CSS */
#menu a {
  color: #111;
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
.post a {
  color: red;
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}

2.嵌套規則(避免嵌套層級過多)

將嵌套深度限制在2-3級。對於超過3級的嵌套,給予從新評估。這能夠避免出現過於詳實的CSS選擇器。 避免大量的嵌套規則。當可讀性受到影響時,將之打斷。推薦避免出現多於20行的嵌套規則出現。

#header {
  color: black;

  .navigation {
    font-size: 12px;
  }
  .logo {
    width: 300px;
    &:hover { text-decoration: none }
  }
}

3.命名空間

有時候,你可能爲了更好組織CSS或者單純是爲了更好的封裝,將一些變量或者混合模塊打包起來, 你能夠像下面這樣在#bundle中定義一些屬性集以後能夠重複使用:

#bundle {
  .button () {
    display: block;
    border: 1px solid black;
    background-color: grey;
    &:hover { background-color: white }
  }
  .tab { ... }
  .citation { ... }
}
/*你只須要在 #header a中像這樣引入 .button:*/
#header a {
  color: orange;
  #bundle > .button;
}

以上HTML和CSS的規範大部分參考github上的frontend-guidelines編碼規範by@mdo(後面幾個本身新增

3、JavaScript

javascript規範使用的是Standard標準,其好處可點擊超連接查看,npm,github等都是使用的此標準。 下文copy的Standard Style的具體規則,配合eslint使用

1. 使用兩個空格進行縮進。

eslint: indent

function hello (name) {
  console.log('hi', name)
}

2.除須要轉義的狀況外,字符串統一使用單引號。

eslint: quotes

console.log('hello there')
$("<div class='box'>")

3.不要定義未使用的變量。

eslint: no-unused-vars

function myFunction () {
  var result = something()   // ✗ avoid
}

4.關鍵字後面加空格。

eslint: keyword-spacing

if (condition) { ... }   // ✓ ok
if(condition) { ... }    // ✗ avoid

5.函數聲明時括號與函數名間加空格。

eslint: space-before-function-paren

function name (arg) { ... }   // ✓ ok
function name(arg) { ... }    // ✗ avoid

run(function () { ... })      // ✓ ok
run(function() { ... })       // ✗ avoid

6.始終使用 === 替代 ==。

例外: obj == null 能夠用來檢查 null || undefined。

eslint: eqeqeq

if (name === 'John')   // ✓ ok
if (name == 'John')    // ✗ avoid
if (name !== 'John')   // ✓ ok
if (name != 'John')    // ✗ avoid

7.字符串拼接操做符 (Infix operators) 之間要留空格。

eslint: space-infix-ops

// ✓ ok
var x = 2
var message = 'hello, ' + name + '!'
// ✗ avoid
var x=2
var message = 'hello, '+name+'!'

8.逗號後面加空格。

eslint: comma-spacing

// ✓ ok
var list = [1, 2, 3, 4]
function greet (name, options) { ... }
// ✗ avoid
var list = [1,2,3,4]
function greet (name,options) { ... }

9.else 關鍵字要與花括號保持在同一行。

eslint: brace-style

// ✓ ok
if (condition) {
  // ...
} else {
  // ...
}
// ✗ avoid
if (condition)
{
  // ...
}
else
{
  // ...
}

10.多行 if 語句的的括號不能省。

eslint: curly

// ✓ ok
if (options.quiet !== true) console.log('done')
// ✓ ok
if (options.quiet !== true) {
  console.log('done')
}
// ✗ avoid
if (options.quiet !== true)
  console.log('done')

11.不要丟掉異常處理中err參數。

eslint: handle-callback-err

// ✓ ok
run(function (err) {
  if (err) throw err
  window.alert('done')
})
// ✗ avoid
run(function (err) {
  window.alert('done')
})

12.使用瀏覽器全局變量時加上 window. 前綴。

例外: document, console and navigator

eslint: no-undef

window.alert('hi')   // ✓ ok

13.不容許有連續多行空行。

eslint: no-multiple-empty-lines

// ✓ ok
var value = 'hello world'
console.log(value)
// ✗ avoid
var value = 'hello world'


console.log(value)

14.對於三元運算符 ? 和 : 與他們所負責的代碼處於同一行。

eslint: operator-linebreak

// ✓ ok
var location = env.development ? 'localhost' : 'www.api.com'

// ✓ ok
var location = env.development
  ? 'localhost'
  : 'www.api.com'
// ✗ avoid
var location = env.development ?
  'localhost' :
  'www.api.com'

15.每一個 var 關鍵字單獨聲明一個變量。

eslint: one-var

// ✓ ok
var silent = true
var verbose = true
// ✗ avoid
var silent = true, verbose = true

// ✗ avoid
var silent = true,
    verbose = true

16.條件語句中賦值語句使用括號包起來。這樣使得代碼更加清晰可讀,而不會認爲是將條件判斷語句的全等號(===)錯寫成了等號(=)。

eslint: no-cond-assign

// ✓ ok
while ((m = text.match(expr))) {
  // ...
}

// ✗ avoid
while (m = text.match(expr)) {
  // ...
}

17.單行代碼塊兩邊加空格。

eslint: block-spacing

function foo () {return true}    // ✗ avoid
function foo () { return true }  // ✓ ok

18.對於變量和函數名統一使用駝峯命名法。

eslint: camelcase

function my_function () { }    // ✗ avoid
function myFunction () { }     // ✓ ok

var my_var = 'hello'           // ✗ avoid
var myVar = 'hello'            // ✓ ok

19.不容許有多餘的行末逗號。

eslint: comma-dangle

var obj = {
    message: 'hello',   // ✗ avoid
  }

20.始終將逗號置於行末。

eslint: comma-style

var obj = {
    foo: 'foo'
    ,bar: 'bar'   // ✗ avoid
  }

  var obj = {
    foo: 'foo',
    bar: 'bar'   // ✓ ok
  }

21.文件末尾留一空行。

elint: eol-last

22.函數調用時標識符與括號間不留間隔。

eslint: func-call-spacing

console.log ('hello') // ✗ avoid
console.log('hello')  // ✓ ok

23.鍵值對當中冒號與值之間要留空白。

eslint: key-spacing

var obj = { 'key' : 'value' }    // ✗ avoid
var obj = { 'key' :'value' }     // ✗ avoid
var obj = { 'key':'value' }      // ✗ avoid
var obj = { 'key': 'value' }     // ✓ ok

24.構造函數要以大寫字母開頭。

eslint: new-cap

function animal () {}
var dog = new animal()    // ✗ avoid
function Animal () {}
var dog = new Animal()    // ✓ ok

25.無參的構造函數調用時要帶上括號。

eslint: new-parens

function Animal () {}
var dog = new Animal    // ✗ avoid
var dog = new Animal()  // ✓ ok

26.對象中定義了存值器,必定要對應的定義取值器。

eslint: accessor-pairs

var person = {
  set name (value) {    // ✗ avoid
    this.name = value
  }
}
var person = {
  set name (value) {
    this.name = value
  },
  get name () {         // ✓ ok
    return this.name
  }
}

27.子類的構造器中必定要調用 super

eslint: constructor-super

class Dog {
  constructor () {
    super()   // ✗ avoid
  }
}

class Dog extends Mammal {
  constructor () {
    super()   // ✓ ok
  }
}

28.使用數組字面量而不是構造器。

eslint: no-array-constructor

var nums = new Array(1, 2, 3)   // ✗ avoid
var nums = [1, 2, 3]            // ✓ ok

29.避免使用 arguments.callee 和 arguments.caller。

eslint: no-caller

function foo (n) {
  if (n <= 0) return

  arguments.callee(n - 1)   // ✗ avoid
}

function foo (n) {
  if (n <= 0) return

  foo(n - 1)
}

30.避免對類名從新賦值。

eslint: no-class-assign

class Dog {}
Dog = 'Fido'    // ✗ avoid

31.避免修改使用 const 聲明的變量。

eslint: no-const-assign

const score = 100
score = 125       // ✗ avoid

32.避免使用常量做爲條件表達式的條件(循環語句除外)。

eslint: no-constant-condition

if (false) {    // ✗ avoid
  // ...
}

if (x === 0) {  // ✓ ok
  // ...
}

while (true) {  // ✓ ok
  // ...
}

33.正則中不要使用控制符。

eslint: no-control-regex

var pattern = /\x1f/    // ✗ avoid
var pattern = /\x20/    // ✓ ok

34.不要使用 debugger。

eslint: no-debugger

function sum (a, b) {
  debugger      // ✗ avoid
  return a + b
}

35.不要對變量使用 delete 操做。

eslint: no-delete-var

var name
delete name     // ✗ avoid

36.不要定義冗餘的函數參數。

eslint: no-dupe-args

function sum (a, b, a) {  // ✗ avoid
  // ...
}

function sum (a, b, c) {  // ✓ ok
  // ...
}

37.類中不要定義冗餘的屬性。

eslint: no-dupe-class-members

class Dog {
  bark () {}
  bark () {}    // ✗ avoid
}

38.對象字面量中不要定義重複的屬性。

eslint: no-dupe-keys

var user = {
  name: 'Jane Doe',
  name: 'John Doe'    // ✗ avoid
}

39.switch 語句中不要定義重複的 case 分支。

eslint: no-duplicate-case

switch (id) {
  case 1:
    // ...
  case 1:     // ✗ avoid
}

40.同一模塊有多個導入時一次性寫完。

eslint: no-duplicate-imports

import { myFunc1 } from 'module'
import { myFunc2 } from 'module'          // ✗ avoid

import { myFunc1, myFunc2 } from 'module' // ✓ ok

41.正則中不要使用空字符。

eslint: no-empty-character-class

const myRegex = /^abc[]/      // ✗ avoid
const myRegex = /^abc[a-z]/   // ✓ ok

42.不要解構空值。

eslint: no-empty-pattern

const { a: {} } = foo         // ✗ avoid
const { a: { b } } = foo      // ✓ ok

43.不要使用 eval()。

eslint: no-eval

eval( "var result = user." + propName ) // ✗ avoid
var result = user[propName]             // ✓ ok

44.catch 中不要對錯誤從新賦值。

eslint: no-ex-assign

try {
  // ...
} catch (e) {
  e = 'new value'             // ✗ avoid
}

try {
  // ...
} catch (e) {
  const newVal = 'new value'  // ✓ ok
}

45.不要擴展原生對象。

eslint: no-extend-native

Object.prototype.age = 21     // ✗ avoid

46.避免多餘的函數上下文綁定。

eslint: no-extra-bind

const name = function () {
  getName()
}.bind(user)    // ✗ avoid

const name = function () {
  this.getName()
}.bind(user)    // ✓ ok

47.避免沒必要要的布爾轉換。

eslint: no-extra-boolean-cast

const result = true
if (!!result) {   // ✗ avoid
  // ...
}

const result = true
if (result) {     // ✓ ok
  // ...
}

48.不要使用多餘的括號包裹函數。

eslint: no-extra-parens

const myFunc = (function () { })   // ✗ avoid
const myFunc = function () { }     // ✓ ok

49.switch 必定要使用 break 來將條件分支正常中斷。

eslint: no-fallthrough

switch (filter) {
  case 1:
    doSomething()    // ✗ avoid
  case 2:
    doSomethingElse()
}

switch (filter) {
  case 1:
    doSomething()
    break           // ✓ ok
  case 2:
    doSomethingElse()
}

switch (filter) {
  case 1:
    doSomething()
    // fallthrough // ✓ ok
  case 2:
    doSomethingElse()
}

50.不要省去小數點前面的0。

eslint: no-floating-decimal

const discount = .5      // ✗ avoid
const discount = 0.5     // ✓ ok

51.避免對聲明過的函數從新賦值。

eslint: no-func-assign

function myFunc () { }
myFunc = myOtherFunc    // ✗ avoid

52.不要對全局只讀對象從新賦值。

eslint: no-global-assign

window = {}     // ✗ avoid

53.注意隱式的 eval()。

eslint: no-implied-eval

setTimeout("alert('Hello world')")                   // ✗ avoid
setTimeout(function () { alert('Hello world') })     // ✓ ok

54.嵌套的代碼塊中禁止再定義函數。

eslint: no-inner-declarations

if (authenticated) {
  function setAuthUser () {}    // ✗ avoid
}

55.不要向 RegExp 構造器傳入非法的正則表達式。

eslint: no-invalid-regexp

RegExp('[a-z')    // ✗ avoid
RegExp('[a-z]')   // ✓ ok

56.不要使用非法的空白符。

eslint: no-irregular-whitespace

function myFunc () /*<NBSP>*/{}   // ✗ avoid

57.禁止使用 iterator

eslint: no-iterator

Foo.prototype.__iterator__ = function () {}   // ✗ avoid

58.外部變量不要與對象屬性重名。

eslint: no-label-var

var score = 100
function game () {
  score: 50         // ✗ avoid
}

59.不要使用標籤語句

eslint: no-labels

label:
  while (true) {
    break label     // ✗ avoid
  }

60.不要書寫沒必要要的嵌套代碼塊。

eslint: no-lone-blocks

function myFunc () {
  {                   // ✗ avoid
    myOtherFunc()
  }
}

function myFunc () {
  myOtherFunc()       // ✓ ok
}

61.不要混合使用空格與製表符做爲縮進。

eslint: no-mixed-spaces-and-tabs

62.除了縮進,不要使用多個空格。

eslint: no-multi-spaces

const id =    1234    // ✗ avoid
const id = 1234       // ✓ ok

63.不要使用多行字符串。

eslint: no-multi-str

const message = 'Hello \ world'     // ✗ avoid

64.new 建立對象實例後須要賦值給變量。

eslint: no-new

new Character()                     // ✗ avoid
const character = new Character()   // ✓ ok

65.禁止使用 Function 構造器。

eslint: no-new-func

var sum = new Function('a', 'b', 'return a + b')    // ✗ avoid

66.禁止使用 Object 構造器。

eslint: no-new-object

let config = new Object()   // ✗ avoid

67.禁止使用 new require。

eslint: no-new-require

const myModule = new require('my-module')    // ✗ avoid

68.禁止使用 Symbol 構造器。

eslint: no-new-symbol

const foo = new Symbol('foo')   // ✗ avoid

69.禁止使用原始包裝器。

eslint: no-new-wrappers

const message = new String('hello')   // ✗ avoid

70.不要將全局對象的屬性做爲函數調用。

eslint: no-obj-calls

const math = Math()   // ✗ avoid

71.不要使用八進制字面量。

eslint: no-octal

const num = 042     // ✗ avoid
const num = '042'   // ✓ ok

72.字符串字面量中也不要使用八進制轉義字符。

eslint: no-octal-escape

const copyright = 'Copyright \251'  // ✗ avoid

73.使用 __dirname 和 __filename 時儘可能避免使用字符串拼接。

eslint: no-path-concat

const pathToFile = __dirname + '/app.js'            // ✗ avoid
const pathToFile = path.join(__dirname, 'app.js')   // ✓ ok

74.使用 getPrototypeOf 來替代 proto

eslint: no-proto

const foo = obj.__proto__               // ✗ avoid
const foo = Object.getPrototypeOf(obj)  // ✓ ok

75.不要重複聲明變量。

eslint: no-redeclare

let name = 'John'
let name = 'Jane'     // ✗ avoid

let name = 'John'
name = 'Jane'         // ✓ ok

76.正則中避免使用多個空格。

eslint: no-regex-spaces

const regexp = /test value/   // ✗ avoid

const regexp = /test {3}value/  // ✓ ok
const regexp = /test value/     // ✓ ok

77.return 語句中的賦值必需有括號包裹。

eslint: no-return-assign

function sum (a, b) {
  return result = a + b     // ✗ avoid
}

function sum (a, b) {
  return (result = a + b)   // ✓ ok
}

78.避免將變量賦值給本身。

eslint: no-self-assign

name = name   // ✗ avoid

79.避免將變量與本身進行比較操做。

esint: no-self-compare

if (score === score) {}   // ✗ avoid

80.避免使用逗號操做符。

eslint: no-sequences

if (doSomething(), !!test) {}   // ✗ avoid

81.不要隨意更改關鍵字的值。

eslint: no-shadow-restricted-names

let undefined = 'value'     // ✗ avoid

82.禁止使用稀疏數組(Sparse arrays)。

eslint: no-sparse-arrays

let fruits = ['apple',, 'orange']       // ✗ avoid

83.不要使用製表符。

eslint: no-tabs

84.正確使用 ES6 中的字符串模板。

eslint: no-template-curly-in-string

const message = 'Hello ${name}'   // ✗ avoid
const message = `Hello ${name}`   // ✓ ok

85.使用 this 前請確保 super() 已調用。

eslint: no-this-before-super

class Dog extends Animal {
  constructor () {
    this.legs = 4     // ✗ avoid
    super()
  }
}

86.用 throw 拋錯時,拋出 Error 對象而不是字符串。

eslint: no-throw-literal

throw 'error'               // ✗ avoid
throw new Error('error')    // ✓ ok

87.行末不留空格。

eslint: no-trailing-spaces

88.不要使用 undefined 來初始化變量。

eslint: no-undef-init

let name = undefined    // ✗ avoid

let name
name = 'value'          // ✓ ok

89.循環語句中注意更新循環變量。

eslint: no-unmodified-loop-condition

for (let i = 0; i < items.length; j++) {...}    // ✗ avoid
for (let i = 0; i < items.length; i++) {...}    // ✓ ok

90.若是有更好的實現,儘可能不要使用三元表達式。

eslint: no-unneeded-ternary

let score = val ? val : 0     // ✗ avoid
let score = val || 0          // ✓ ok

91.return,throw,continue 和 break 後不要再跟代碼。

eslint: no-unreachable

function doSomething () {
  return true
  console.log('never called')     // ✗ avoid
}

92.finally 代碼塊中不要再改變程序執行流程。

eslint: no-unsafe-finally

try {
  // ...
} catch (e) {
  // ...
} finally {
  return 42     // ✗ avoid
}

93.關係運算符的左值不要作取反操做。

eslint: no-unsafe-negation

if (!key in obj) {}       // ✗ avoid

94.避免沒必要要的 .call() 和 .apply()。

eslint: no-useless-call

sum.call(null, 1, 2, 3)   // ✗ avoid

95.避免使用沒必要要的計算值做對象屬性。

eslint: no-useless-computed-key

const user = { ['name']: 'John Doe' }   // ✗ avoid
const user = { name: 'John Doe' }       // ✓ ok

96.禁止多餘的構造器。

eslint: no-useless-constructor

class Car {
  constructor () {      // ✗ avoid
  }
}

97.禁止沒必要要的轉義。

eslint: no-useless-escape

let message = 'Hell\o'  // ✗ avoid

98.import, export 和解構操做中,禁止賦值到同名變量。

eslint: no-useless-rename

import { config as config } from './config'     // ✗ avoid
import { config } from './config'               // ✓ ok

99.屬性前面不要加空格。

eslint: no-whitespace-before-property

user .name      // ✗ avoid
user.name       // ✓ ok

100.禁止使用 with。

eslint: no-with

with (val) {...}    // ✗ avoid

101.對象屬性換行時注意統一代碼風格。

eslint: object-property-newline

const user = {
  name: 'Jane Doe', age: 30,
  username: 'jdoe86'            // ✗ avoid
}

const user = { name: 'Jane Doe', age: 30, username: 'jdoe86' }    // ✓ ok

const user = {
  name: 'Jane Doe',
  age: 30,
  username: 'jdoe86'
}

102.代碼塊中避免多餘留白。

eslint: padded-blocks

if (user) {
                            // ✗ avoid
  const name = getName()

}

if (user) {
  const name = getName()    // ✓ ok
}

103.展開運算符與它的表達式間不要留空白。

eslint: rest-spread-spacing

fn(... args)    // ✗ avoid
fn(...args)     // ✓ ok

104.遇到分號時空格要後留前不留。

eslint: semi-spacing

for (let i = 0 ;i < items.length ;i++) {...}    // ✗ avoid
for (let i = 0; i < items.length; i++) {...}    // ✓ ok

105.代碼塊首尾留空格。

eslint: space-before-blocks

if (admin){...}     // ✗ avoid
if (admin) {...}    // ✓ ok

106.圓括號間不留空格

eslint: space-in-parens

getName( name )     // ✗ avoid
getName(name)       // ✓ ok

107.一元運算符後面跟一個空格。

eslint: space-unary-ops

typeof!admin        // ✗ avoid
typeof !admin        // ✓ ok

108.註釋首尾留空格。

eslint: spaced-comment

//comment // ✗ avoid
// comment // ✓ ok

/*comment*/         // ✗ avoid
/* comment */       // ✓ ok

109.模板字符串中變量先後不加空格。

eslint: template-curly-spacing

const message = `Hello, ${ name }`    // ✗ avoid
const message = `Hello, ${name}`      // ✓ ok

110.檢查 NaN 的正確姿式是使用 isNaN()。

eslint: use-isnan

if (price === NaN) { }      // ✗ avoid
if (isNaN(price)) { }       // ✓ ok

111.用合法的字符串跟 typeof 進行比較操做。

eslint: valid-typeof

typeof name === 'undefimed'     // ✗ avoid
typeof name === 'undefined'     // ✓ ok

112.自調用匿名函數 (IIFEs) 使用括號包裹。

eslint: wrap-iife

const getName = function () { }()     // ✗ avoid

const getName = (function () { }())   // ✓ ok
const getName = (function () { })()   // ✓ ok

113.yield * 中的 * 先後都要有空格。

eslint: yield-star-spacing

yield* increment()    // ✗ avoid
yield * increment()   // ✓ ok

114.請書寫優雅的條件語句(avoid Yoda conditions)。

eslint: yoda

if (42 === age) { }    // ✗ avoid
if (age === 42) { }    // ✓ ok

115.使用分號。

eslint: semi

window.alert('hi')   // ✗ avoid
window.alert('hi');  // ✓ ok

116.不要使用 (, [, or ` 等做爲一行的開始。在沒有分號的狀況下代碼壓縮後會致使報錯,而堅持這一規範則可避免出錯。

** eslint: no-unexpected-multiline **

// ✓ ok
;(function () {
  window.alert('ok')
}())

// ✗ avoid
(function () {
  window.alert('ok')
}())
// ✓ ok
;[1, 2, 3].forEach(bar)

// ✗ avoid
[1, 2, 3].forEach(bar)
// ✓ ok
;`hello`.indexOf('o')

// ✗ avoid
`hello`.indexOf('o')

備註:上面的寫法只能說聰明過頭了。

相比更加可讀易懂的代碼,那些看似投巧的寫法是不可取的。

譬如:

;[1, 2, 3].forEach(bar)

建議的寫法是:

var nums = [1, 2, 3]
nums.forEach(bar)

es6語法規範

1.let 取代 var

ES6 提出了兩個新的聲明變量的命令:let和const。其中,let徹底能夠取代var,由於二者語義相同,並且let沒有反作用。

2.全局常量const

在全局環境,不該該設置變量,只應設置常量

好處:const優於let有幾個緣由。一個是const能夠提醒閱讀程序的人,這個變量不該該改變;另外一個是const比較符合函數式編程思想,運算不改變值,只是新建值,並且這樣也有利於未來的分佈式運算;最後一個緣由是 JavaScript 編譯器會對const進行優化,因此多使用const,有利於提升程序的運行效率,也就是說letconst的本質區別,實際上是編譯器內部的處理不一樣。 const聲明常量還有兩個好處,一是閱讀代碼的人馬上會意識到不該該修改這個值,二是防止了無心間修改變量值所致使的錯誤。

3.使用解構賦值

使用數組成員對變量賦值時,優先使用解構賦值。

const arr = [1, 2, 3, 4];

// bad
const first = arr[0];
const second = arr[1];

// good
const [first, second] = arr;

函數的參數若是是對象的成員,優先使用解構賦值。

// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;
}

// good
function getFullName(obj) {
  const { firstName, lastName } = obj;
}

// best
function getFullName({ firstName, lastName }) {
}

若是函數返回多個值,優先使用對象的解構賦值,而不是數組的解構賦值。這樣便於之後添加返回值,以及更改返回值的順序。

// bad
function processInput(input) {
  return [left, right, top, bottom];
}

// good
function processInput(input) {
  return { left, right, top, bottom };
}

const { left, right } = processInput(input);

4.對象

對象儘可能靜態化,一旦定義,就不得隨意添加新的屬性。若是添加屬性不可避免,要使用Object.assign方法。

// bad
const a = {};
a.x = 3;

// if reshape unavoidable
const a = {};
Object.assign(a, { x: 3 });

// good
const a = { x: null };
a.x = 3;

若是對象的屬性名是動態的,能夠在創造對象的時候,使用屬性表達式定義。

// bad
const obj = {
  id: 5,
  name: 'San Francisco',
};
obj[getKey('enabled')] = true;

// good
const obj = {
  id: 5,
  name: 'San Francisco',
  [getKey('enabled')]: true,
};

另外,對象的屬性和方法,儘可能採用簡潔表達法,這樣易於描述和書寫。

var ref = 'some value';

// bad
const atom = {
  ref: ref,

  value: 1,

  addValue: function (value) {
    return atom.value + value;
  },
};

// good
const atom = {
  ref,

  value: 1,

  addValue(value) {
    return atom.value + value;
  },
};

5.數組

使用擴展運算符(...)拷貝數組。

// bad
const len = items.length;
const itemsCopy = [];
let i;

for (i = 0; i < len; i++) {
  itemsCopy[i] = items[i];
}

// good
const itemsCopy = [...items];

使用 Array.from 方法,將相似數組的對象轉爲數組。

const foo = document.querySelectorAll('.foo');
const nodes = Array.from(foo);

6.函數

當即執行函數能夠寫成箭頭函數的形式。

(() => {
  console.log('Welcome to the Internet.');
})();

那些須要使用函數表達式的場合,儘可能用箭頭函數代替。由於這樣更簡潔,並且綁定了 this。

// bad
[1, 2, 3].map(function (x) {
  return x * x;
});

// good
[1, 2, 3].map((x) => {
  return x * x;
});

// best
[1, 2, 3].map(x => x * x);

簡單的、單行的、不會複用的函數,建議採用箭頭函數。若是函數體較爲複雜,行數較多,仍是應該採用傳統的函數寫法。

7.Map結構

注意區分 Object 和 Map,只有模擬現實世界的實體對象時,才使用 Object。若是隻是須要key: value的數據結構,使用 Map 結構。由於 Map 有內建的遍歷機制。

let map = new Map(arr);

for (let key of map.keys()) {
  console.log(key);
}

for (let value of map.values()) {
  console.log(value);
}

for (let item of map.entries()) {
  console.log(item[0], item[1]);
}

8.class

老是用 Class,取代須要 prototype 的操做。由於 Class 的寫法更簡潔,更易於理解。

// bad
function Queue(contents = []) {
  this._queue = [...contents];
}
Queue.prototype.pop = function() {
  const value = this._queue[0];
  this._queue.splice(0, 1);
  return value;
}

// good
class Queue {
  constructor(contents = []) {
    this._queue = [...contents];
  }
  pop() {
    const value = this._queue[0];
    this._queue.splice(0, 1);
    return value;
  }
}

使用extends實現繼承,由於這樣更簡單,不會有破壞instanceof運算的危險。

// bad
const inherits = require('inherits');
function PeekableQueue(contents) {
  Queue.apply(this, contents);
}
inherits(PeekableQueue, Queue);
PeekableQueue.prototype.peek = function() {
  return this._queue[0];
}

// good
class PeekableQueue extends Queue {
  peek() {
    return this._queue[0];
  }
}

9.使用promise時

通常來講,不要在then方法裏面定義失敗狀態的回調函數(即then的第二個參數),老是使用catch方法

// bad
promise
  .then(function(data) {
    // success
  }, function(err) {
    // error
  });

// good
promise
  .then(function(data) { //cb
    // success
  })
  .catch(function(err) {
    // error
  });

新增

i++

儘可能不要使用i++,儘可能使用i+=1;(除了for循環)

4、vue規範

1.vue方法放置順序

1.1 components

1.2 props

1.3 data

1.4 created

1.5 mounted

1.6 activited

1.7 update

1.8 beforeRouteUpdate

1.9 metods

1.10 filter

1.11 computed

1.12 watch

2.method 自定義方法命名

2.1 動賓短語(good:jumpPage、openCarInfoDialog)(bad:go、nextPage、show、open、login)

2.2 ajax 方法以 get、post 開頭,以 data 結尾(good:getListData、postFormData)(bad:takeData、confirmData、getList、postForm)

2.3 事件方法以 on 開頭(onTypeChange、onUsernameInput)

2.4 init、refresh 單詞除外

2.5 儘可能使用經常使用單詞開頭(set、get、open、close、jump)

2.6 駝峯命名(good: getListData)(bad: get_list_data、getlistData)

3.生命週期方法注意點

3.1 不在 mounted、created 之類的方法寫邏輯,取 ajax 數據,

3.2 在 created 裏面監聽 Bus 事件

4.基於模塊開發

原則:每個vue組件首先必須專一於解決一個單一的問題,獨立的,可複用的,微小的和可測試的。 若是你的組件作了太多的事或是變得臃腫,請將其拆成更小的組件並保持單一的原則。

5.Vue 組件命名

  • 有意義的: 不過於具體,也不過於抽象
  • 簡短: 2 到 3 個單詞
  • 具備可讀性: 以便於溝通交流
<!-- 推薦 -->
<app-header></app-header>
<user-list></user-list>
<range-slider></range-slider>

<!-- 避免 -->
<btn-group></btn-group> <!-- 雖然簡短可是可讀性差. 使用 `button-group` 替代 -->
<ui-slider></ui-slider> <!-- ui 前綴太過於寬泛,在這裏意義不明確 -->
<slider></slider> <!-- 與自定義元素規範不兼容 -->

6.驗證組件的props

  • 提供默認值。
  • 使用 type 屬性校驗類型。
  • 使用 props 以前先檢查該 prop 是否存在。
<template>
  <input type="range" v-model="value" :max="max" :min="min">
</template>
<script type="text/javascript">
  export default {
    props: {
      max: {
        type: Number, // 這裏添加了數字類型的校驗
        default() { return 10; },
      },
      min: {
        type: Number,
        default() { return 0; },
      },
      value: {
        type: Number,
        default() { return 4; },
      },
    },
  };
</script>

7.只在須要時建立組件

Vue.js 是一個基於組件的框架。若是你不知道什麼時候建立組件可能會致使如下問題:

  • 若是組件太大, 可能很難重用和維護;
  • 若是組件過小,你的項目就會(由於深層次的嵌套而)被淹沒,也更難使組件間通訊;

規則

  • 首先,儘量早地嘗試構建出諸如模態框、提示框、工具條、菜單、頭部等這些明顯的(通用型)組件。總之,你知道的這些組件之後必定會在當前頁面或者是全局範圍內須要。

  • 第二,在每個新的開發項目中,對於一整個頁面或者其中的一部分,在進行開發前先嚐試思考一下。若是你認爲它有一部分應該是一個組件,那麼就建立它吧。

  • 最後,若是你不肯定,那就不要。避免那些「之後可能會有用」的組件污染你的項目。它們可能會永遠的只是(靜靜地)待在那裏,這一點也不聰明。注意,一旦你意識到應該這麼作,最好是就把它打破,以免與項目的其餘部分構成兼容性和複雜性。

註釋規範

1.在vscode中使用vscode-fileheader插件,生成頭部文件註釋

2.普通的註釋

2.1 老是在單行註釋符後留一個空格

// this is comment

2.2 老是在多行註釋的結束符前留一個空格(使星號對齊)

/* */

2.3 不要把註釋寫在多行註釋的開始符、結束符所在行

// bad

/* start end */

// good
/* here is line 1 here is line 2 */

2.4 不要編寫無心義的註釋

// 初始化value變量爲0
var value = 0;

2.5 若是某段代碼有功能未實現,或者有待完善,必須添加「TODO」標記,「TODO」先後應留一個空格

// TODO 未處理IE6-8的兼容性
function setOpacity(node, val) {
    node.style.opacity = val;
}

3.文檔註釋

文檔註釋將會以預約格式出如今API文檔中。它以「/」開頭,以「/」結束,其間的每一行均以「」開頭(均與開始符的第一個「」對齊),且註釋內容與「」間留一個空格。

3.1 @module。聲明模塊

/** * 模塊說明 * @module 模塊名 */

/** * Core模塊提供最基礎、最核心的接口 * @module Core */

3.2 @class。聲明類

/** * 類說明 * @class 類名 * @constructor */

@class必須搭配@constructor或@static使用,分別標記非靜態類與靜態類。

/** * 節點集合類 * @class NodeList * @constructor * @param {ArrayLike<Element>} nodes 初始化節點 */

3.3 @method。聲明函數或類方法

/** * 方法說明 * @method 方法名 * @for 所屬類名 * @param {參數類型} 參數名 參數說明 * @return {返回值類型} 返回值說明 */

沒有指定@for時,表示此函數爲全局或模塊頂層函數。當函數爲靜態函數時,必須添加@static;當函數有參數時,必須使用@param;當函數有返回值時,必須使用@return。

/** * 返回當前集合中指定位置的元素 * @method * @for NodeList * @param {Number} [i=0] 位置下標。若是爲負數,則從集合的最後一個元素開始倒數 * @return {Element} 指定元素 */

- @param。聲明函數參數,必須與@method搭配使用。
- 當參數出現如下狀況時,使用對應的格式:[參數名]
- 參數有默認值 [參數名 = 默認值]

3.4 @property。聲明類屬性

/** * 屬性說明 * @property {屬性類型} 屬性名 */

 

個人博客即將同步至騰訊雲+社區,邀請你們一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=1n5nbfpbs3gam

相關文章
相關標籤/搜索