天天看點

最全面的前端開發指南

html

語義

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> 

      <p>published: <time datetime="2015-02-21">21st feb, 2015</time></p> 

    </header> 

  </article> 

</main> 

你需要了解你正在使用的元素的語義。用一種錯誤的方式使用語義元素比保持中立更糟糕。

<h1> 

  <figure> 

    <img alt=company src=logo.png> 

  </figure> 

</h1> 

  <img alt=company src=logo.png> 

簡潔

保持代碼的簡潔。忘記原來的xhtml習慣。

<!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 [email protected] required=required /> 

    </label> 

    <script src=main.js type=text/javascript></script> 

  </body> 

</html> 

  <meta charset=utf-8> 

  <title>contact</title> 

  <link rel=stylesheet href=style.css> 

  <h1>contact me</h1> 

  <label> 

    email address: 

    <input type=email [email protected] required> 

  </label> 

  <script src=main.js></script> 

可通路性

可通路性不應該是以後再想的事情。提高網站不需要你成為一個wcag專家,你完全可以通過修複一些小問題,進而造成一個巨大的變化,例如:

學習正确使用<code>alt</code> 屬性

確定連結和按鈕被同樣地标記(不允許&lt;div&gt;)

不專門依靠顔色來傳遞資訊

明确标注表單控件

&lt;h1&gt;&lt;img alt="logo" src="logo.png"&gt;&lt;/h1&gt; 

&lt;h1&gt;&lt;img alt="my company, inc." src="logo.png"&gt;&lt;/h1&gt; 

語言

當定義語言和字元編碼是可選擇的時候,總是建議在文檔級别同時聲明,即使它們在你的http标頭已經詳細說明。比任何其他字元編碼更偏愛utf-8。

&lt;title&gt;hello, world.&lt;/title&gt; 

  &lt;title&gt;hello, world.&lt;/title&gt; 

性能

除非有正當理由才能在内容前加載腳本,不要阻塞頁面的渲染。如果你的樣式表很重,開頭就孤立那些絕對需要得樣式,并在一個單獨的樣式表中推遲二次聲明的加載。兩個http請求顯然比一個慢,但是感覺速度是最重要的因素。

&lt;meta charset=utf-8&gt; 

&lt;script src=analytics.js&gt;&lt;/script&gt; 

&lt;p&gt;...&lt;/p&gt; 

css

分号

雖然分号在技術上是css一個分隔符,但應該始終把它作為一個終止符。

/* bad */ 

div { 

  color: red 

/* good */ 

  color: red; 

盒子模型

盒子模型對于整個文檔而言最好是相同的。全局性的* { box-sizing: border-box; }就非常不錯,但是不要改變預設盒子模型的特定元素,如果可以避免的話。

  width: 100%; 

  padding: 10px; 

  box-sizing: border-box; 

不要更改元素的預設行為,如果可以避免的話。元素盡可能地保持在自然的文檔流中。例如,删除圖像下方的空格而不改變其預設顯示:

img { 

  display: block; 

  vertical-align: middle; 

同樣,如果可以避免的話,不要關閉元素流。

  width: 100px; 

  position: absolute; 

  right: 0; 

  margin-left: auto; 

定位

在css中有許多定位元素的方法,但應該盡量限制以下屬性/值。按優先順序排列:

display: block; 

display: flex; 

position: relative; 

position: sticky; 

position: absolute; 

position: fixed; 

選擇器

最小化緊密耦合到dom的選擇器。當選擇器有多于3個結構僞類,後代或兄弟選擇器的時候,考慮添加一個類到你想比對的元素。

div:first-of-type :last-child &gt; p ~ * 

div:first-of-type .info 

當你不需要的時候避免過載選擇器。

img[src$=svg], ul &gt; li:first-child { 

  opacity: 0; 

[src$=svg], ul &gt; :first-child { 

特異性

不要讓值和選擇器難以覆寫。盡量少用id,并避免!important。

.bar { 

  color: green !important; 

.foo { 

.foo.bar { 

  color: green; 

覆寫

覆寫樣式使得選擇器和調試變得困難。如果可能的話,避免覆寫樣式。

li { 

  visibility: hidden; 

li:first-child { 

  visibility: visible; 

li + li { 

繼承

不要重複可以繼承的樣式聲明。

div h1, div p { 

  text-shadow: 0 1px 0 #fff; 

保持代碼的簡潔。使用簡寫屬性,沒有必要的話,要避免使用多個屬性。

  transition: all 1s; 

  top: 50%; 

  margin-top: -10px; 

  padding-top: 5px; 

  padding-right: 10px; 

  padding-bottom: 20px; 

  padding-left: 10px; 

  transition: 1s; 

  top: calc(50% - 10px); 

  padding: 5px 10px 20px; 

英語表達優于數學公式。

:nth-child(2n + 1) { 

  transform: rotate(360deg); 

:nth-child(odd) { 

  transform: rotate(1turn); 

浏覽器引擎字首

果斷地删除過時的浏覽器引擎字首。如果需要使用的話,可以在标準屬性前插入它們。

  transform: scale(2); 

  -webkit-transform: scale(2); 

  -moz-transform: scale(2); 

  -ms-transform: scale(2); 

  -webkit-transition: 1s; 

  -moz-transition: 1s; 

  -ms-transition: 1s; 

動畫

視圖轉換優于動畫。除了<code>opacity</code> 和transform,避免動畫其他屬性。

div:hover { 

  animation: move 1s forwards; 

@keyframes move { 

  100% { 

    margin-left: 100px; 

  } 

  transform: translatex(100px); 

機關

可以的話,使用無機關的值。如果使用相對機關,那就用<code>rem</code> 。秒優于毫秒。

  margin: 0px; 

  font-size: .9em; 

  line-height: 22px; 

  transition: 500ms; 

  margin: 0; 

  font-size: .9rem; 

  line-height: 1.5; 

  transition: .5s; 

顔色

如果你需要透明度,使用rgba。另外,始終使用十六進制格式。

  color: hsl(103, 54%, 43%); 

  color: #5a3; 

繪畫

當資源很容易用css複制的時候,避免http請求。

div::before { 

  content: url(white-circle.svg); 

  content: ""; 

  width: 20px; 

  height: 20px; 

  border-radius: 50%; 

  background: #fff; 

hacks

不要使用hacks。

  // position: relative; 

  transform: translatez(0); 

  /* position: relative; */ 

  will-change: transform; 

javascript

可讀性,正确性和可表達性優于性能。javascript基本上永遠不會是你的性能瓶頸。圖像壓縮,網絡接入和dom重排來代替優化。如果從本文中你隻能記住一個指導原則,那麼毫無疑問就是這一條。

// bad (albeit way faster) 

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

const len = arr.length; 

var i = -1; 

var result = []; 

while (++i &lt; len) { 

  var n = arr[i]; 

  if (n % 2 &gt; 0) continue; 

  result.push(n * n); 

// good 

const iseven = n =&gt; n % 2 == 0; 

const square = n =&gt; n * n; 

const result = arr.filter(iseven).map(square); 

無狀态

盡量保持函數純潔。理論上,所有函數都不會産生副作用,不會使用外部資料,并且會傳回新對象,而不是改變現有的對象。

// bad 

const merge = (target, ...sources) =&gt; object.assign(target, ...sources); 

merge({ foo: "foo" }, { bar: "bar" }); // =&gt; { foo: "foo", bar: "bar" } 

const merge = (...sources) =&gt; object.assign({}, ...sources); 

本地化

盡可能地依賴本地方法。

const toarray = obj =&gt; [].slice.call(obj); 

const toarray = (() =&gt; 

  array.from ? array.from : obj =&gt; [].slice.call(obj) 

)(); 

強制性

如果強制有意義,那麼就使用隐式強制。否則就應該避免強制。

if (x === undefined || x === null) { ... } 

if (x == undefined) { ... } 

循環

不要使用循環,因為它們會強迫你使用可變對象。依靠<code>array.prototype</code> 方法。

const sum = arr =&gt; { 

  var sum = 0; 

  var i = -1; 

  for (;arr[++i];) { 

    sum += arr[i]; 

  return sum; 

}; 

sum([1, 2, 3]); // =&gt; 6 

const sum = arr =&gt; 

  arr.reduce((x, y) =&gt; x + y); 

如果不能避免,或使用<code>array.prototype</code> 方法濫用了,那就使用遞歸。

const createdivs = howmany =&gt; { 

  while (howmany--) { 

    document.body.insertadjacenthtml("beforeend", "&lt;div&gt;&lt;/div&gt;"); 

createdivs(5); 

const createdivs = howmany =&gt; 

  [...array(howmany)].foreach(() =&gt; 

    document.body.insertadjacenthtml("beforeend", "&lt;div&gt;&lt;/div&gt;") 

  ); 

  if (!howmany) return; 

  document.body.insertadjacenthtml("beforeend", "&lt;div&gt;&lt;/div&gt;"); 

  return createdivs(howmany - 1); 

這裡有一個通用的循環功能,可以讓遞歸更容易使用。

參數

忘記<code>arguments</code> 對象。餘下的參數往往是一個更好的選擇,這是因為:

你可以從它的命名中更好地了解函數需要什麼樣的參數

真實數組,更易于使用。

const sortnumbers = () =&gt; 

  array.prototype.slice.call(arguments).sort(); 

const sortnumbers = (...numbers) =&gt; numbers.sort(); 

應用

忘掉apply()。使用操作符。

const greet = (first, last) =&gt; `hi ${first} ${last}`; 

const person = ["john", "doe"]; 

greet.apply(null, person); 

greet(...person); 

綁定

當有更慣用的做法時,就不要用bind() 。

["foo", "bar"].foreach(func.bind(this)); 

["foo", "bar"].foreach(func, this); 

const person = { 

  first: "john", 

  last: "doe", 

  greet() { 

    const full = function() { 

      return `${this.first} ${this.last}`; 

    }.bind(this); 

    return `hello ${full()}`; 

    const full = () =&gt; `${this.first} ${this.last}`; 

函數嵌套

沒有必要的話,就不要嵌套函數。

[1, 2, 3].map(num =&gt; string(num)); 

[1, 2, 3].map(string); 

合成函數

避免調用多重嵌套函數。使用合成函數來替代。

const plus1 = a =&gt; a + 1; 

const mult2 = a =&gt; a * 2; 

mult2(plus1(5)); // =&gt; 12 

const pipeline = (...funcs) =&gt; val =&gt; funcs.reduce((a, b) =&gt; b(a), val); 

const addthenmult = pipeline(plus1, mult2); 

addthenmult(5); // =&gt; 12 

緩存

緩存功能測試,大資料結構和任何奢侈的操作。

const contains = (arr, value) =&gt; 

  array.prototype.includes 

    ? arr.includes(value) 

    : arr.some(el =&gt; el === value); 

contains(["foo", "bar"], "baz"); // =&gt; false 

const contains = (() =&gt; 

    ? (arr, value) =&gt; arr.includes(value) 

    : (arr, value) =&gt; arr.some(el =&gt; el === value) 

變量

<code>const</code> 優于<code>let</code> ,<code>let</code> 優于var。

var me = new map(); 

me.set("name", "ben").set("country", "belgium"); 

const me = new map(); 

條件

iife 和return 語句優于if, else if,else和switch語句。

var grade; 

if (result &lt; 50) 

  grade = "bad"; 

else if (result &lt; 90) 

  grade = "good"; 

else 

  grade = "excellent"; 

const grade = (() =&gt; { 

  if (result &lt; 50) 

    return "bad"; 

  if (result &lt; 90) 

    return "good"; 

  return "excellent"; 

})(); 

對象疊代

如果可以的話,避免for…in。

const shared = { foo: "foo" }; 

const obj = object.create(shared, { 

  bar: { 

    value: "bar", 

    enumerable: true 

}); 

for (var prop in obj) { 

  if (obj.hasownproperty(prop)) 

    console.log(prop); 

object.keys(obj).foreach(prop =&gt; console.log(prop)); 

map對象

在對象有合法用例的情況下,map通常是一個更好,更強大的選擇。

const me = { 

  name: "ben", 

  age: 30 

var mesize = object.keys(me).length; 

mesize; // =&gt; 2 

me.country = "belgium"; 

mesize++; 

mesize; // =&gt; 3 

me.set("name", "ben"); 

me.set("age", 30); 

me.size; // =&gt; 2 

me.set("country", "belgium"); 

me.size; // =&gt; 3 

curry

curry雖然功能強大,但對于許多開發人員來說是一個外來的範式。不要濫用,因為其視情況而定的用例相當不尋常。

const sum = a =&gt; b =&gt; a + b; 

sum(5)(3); // =&gt; 8 

const sum = (a, b) =&gt; a + b; 

sum(5, 3); // =&gt; 8 

可讀性

不要用看似聰明的伎倆混淆代碼的意圖。

foo || dosomething(); 

if (!foo) dosomething(); 

void function() { /* iife */ }(); 

(function() { /* iife */ }()); 

const n = ~~3.14; 

const n = math.floor(3.14); 

代碼重用

不要害怕建立小型的,高度可組合的,可重複使用的函數。

arr[arr.length - 1]; 

const first = arr =&gt; arr[0]; 

const last = arr =&gt; first(arr.slice(-1)); 

last(arr); 

const product = (a, b) =&gt; a * b; 

const triple = n =&gt; n * 3; 

const triple = product.bind(null, 3); 

依賴性

最小化依賴性。第三方是你不知道的代碼。不要隻是因為幾個可輕易複制的方法而加載整個庫:

var _ = require("underscore"); 

_.compact(["foo", 0])); 

_.unique(["foo", "foo"]); 

_.union(["foo"], ["bar"], ["foo"]); 

const compact = arr =&gt; arr.filter(el =&gt; el); 

const unique = arr =&gt; [...set(arr)]; 

const union = (...arr) =&gt; unique([].concat(...arr)); 

compact(["foo", 0]); 

unique(["foo", "foo"]); 

union(["foo"], ["bar"], ["foo"]); 

作者:小峰

來源:51cto