一、HTML編碼規範1. img標籤要寫alt屬性根據W3C標準,img標籤要寫alt屬性,如果沒有就寫一個空的。但是一般要寫一個有內容的,根據圖片想要表達的意思,因為alt是在圖片無法加載時顯示的文字。如下不太好的寫法: 更好的寫法: 這裡就不用告訴用戶它是一個Logo了,直接告訴它是ABC Compay就好了。再如: 可改成: 如果圖片顯示不出來,就直接顯示用戶的名字。 有些人偷懶就直接寫個空的alt那也可以,但是在一些重要的地方還是要寫一下,畢竟它還是有利於SEO. 2. 單標籤不要寫閉合標籤為什麼?因為寫了也沒用,還顯得你不懂html規範,我們不是寫XHTML。常見的單標籤有img、link、input、hr、br,如下不好的寫法: 應改成: 如果你用React寫jsx模板,它就要求每個標籤都要閉合,但是它始終不是原生html. 3. 自定義屬性要以data-開頭自己添加的非標準的屬性要以data-開頭,否則w3c validator會認為是不規範的,如下不好的寫法: 應改成:
4. td要在tr裡面,li要在ul/ol裡面如下不好的寫法: 更常見的是td沒有寫在tr裡面: 如果你寫得不規範,有些瀏覽器會幫你矯正,但是有些可能就沒有那麼幸運。因為標準並沒有說如果寫得不規範應該怎麼處理,各家瀏覽器可能有自己的處理方式。 5. ul/ol的直接子元素只能是li有時候可能會直接在ul裡面寫一個div或者span,以為這樣沒關係: 這樣寫也是不規範的,不能直接在ol裡面寫span,ol是一個列表,它的子元素應該都是display: list-item的,突然冒出來個span,你讓瀏覽器如何自處。所以寫得不規範就會導致在不同的瀏覽器會有不同的表現。 同樣,tr的直接子元素都應該是td,你在td裡面寫tr那就亂了。 6. section裡面要有標題標籤如果你用了section/aside/article/nav這種標籤的話,需要在裡面寫一個h1/h2/h3之類的標題標籤,因為這四個標籤可以劃分章節,它們都是獨立的章節,需要有標題,如果UI裡面根本就沒有標題呢?那你可以寫一個隱藏的標題標籤,如果出於SEO的目的,你不能直接display: none,而要用一些特殊的處理方式,如下套一個hidden-text的類:
7. 使用section標籤增強SEO使用section的好處是可以劃分章節,如下代碼: 就會被outline成這樣的大綱: Listing Detail
可以使用html5 outliner進行實驗,可以看到,我們很任性地使用了多個h1標籤,這個在html4里面是不合法的。 8. 行內元素裡面不可使用塊級元素例如下面的寫法是不合法的: a標籤是一個行內元素,行內元素裡面套了一個div的標籤,這樣可能會導致a標籤無法正常點擊。再或者是span裡面套了div,這種情況下需要把inline元素顯式地設置display為block,如下代碼: 這樣就正常了。 9. 每個頁面要寫<!DOCType html>設置頁面的渲染模式為標準模式,如果忘記寫了會怎麼樣?忘記寫了會變成怪異模式,怪異模式下很多東西渲染會有所不同,怪異模式下input/textarea的默認盒模型會變成border-box,文檔高度會變成可視窗口的高度,獲取window的高度時就不是期望的文檔高度。還有一個區別,父容器行高在怪異模式下將不會影響子元素,如下代碼: 在標準模式下div下方會留點空白,而在怪異模式下會。這個就提醒我們在寫郵件模板時需要在頂部加上<!DOCType html>,因為在本地開發郵件模板時是寫html片段,沒有這個的話就會變成怪異模式。 10. 要用table佈局寫郵件模板由於郵件客戶端多種多樣,你不知道用戶是使用什麼看的郵件,有可能是用的網頁郵箱,也有可能用的gmail/outlook/網易郵箱大師等客戶端。這些客戶端多種多樣,對html/css的支持也不一,所以我們不能使用高級的佈局和排版,例如flex/float/absolute定位,使用較初級的table佈局能夠達到兼容性最好的效果,並且還有伸縮的效果。 另外郵件模板裡面不能寫媒體查詢,不能寫script,不能寫外聯樣式,這些都會被郵件客戶端過濾掉,樣式都得用內聯style,你可以先寫成外聯,然後再用一些工具幫你生成內聯html。 寫完後要實際測一下,可以用QQ郵箱發送,它支持發送html格式文本,發完後在不同的客戶端打開看一下,看有沒有問題,如手機的客戶端,電腦的客戶端,以及瀏覽器。 由於你不知道用戶是用手機打開還是電腦打開,所以你不能把郵件內容的寬度寫死,但是完全100%也不好,在PC大屏幕上看起來可能會太大,所以一般可以這樣寫: 最外面的table寬度100%,裡面的table有一個max-width:600px,相對於外面的table居中。這樣在PC上最大寬度就為600px,而在手機客戶端上寬度就為100%。 但是有些客戶端如比較老的outlook無法識別max-width的屬性,導致在PC上太寬。但是這個沒有辦法,因為我們不能直接把寬度寫死不然在手機上就要左右滑了,也不能寫script判斷ua之類的方法。所以無法兼容較老版本outlook. 11. html要保持簡潔,不要套太多層需要套很多層的,一般有兩種情況,一種是切圖不太會,需要套很多層來維持排版,第二種是會切圖,但是把UI拆解得太細。像以下佈局: 我會這麼寫: 因為它是一個列表,所以外面用ul/li作為容器,裡面就兩個div,一個圖片的float: left,另外一個文字的容器,這樣就可以了。不用套很多層,但是有一些是必要的,你寫得太簡單的話,擴展性不好,例如它是一個列表那你就應該使用ul/ol,如果你要清除浮動,那你可能需要套一個clearfix的容器。 如果有一塊是整體,它整體向右排版,那麼這一塊也要套一個容器,有時候為了實現一些效果,可能也要多套一個容器,例如讓外面的容器float,而裡面的容器display: table-cell。但是你套這些容器應該都是有價值,如果你只是為了在功能上看起來整齊劃一,區分明顯好像沒太大的意義。 12. 特殊情況下才在html裡面寫script和style通常來說,在html裡面直接寫script和style是一種不好的實踐,這樣把樣式、結構和邏輯都摻雜在一起了。但是有時候為了避免閃屏的問題,可能會直接在相應的html後面跟上調整的script,這種script看起來有點醜陋,但是很實用,是沒有辦法的辦法。 13. 樣式要寫在head標籤裡樣式不能寫在body裡,寫在body裡會導致渲染兩次,特別是寫得越靠後,可能會出現閃屏的情況,例如上面的已經渲染好了,突然遇到一個style標籤,導致它要重新渲染,這樣就閃了一下,不管是從碼農的追求還是用戶的體驗,在body裡面寫style終究是一種下策。 同樣地script不要寫在head標籤裡面,會阻礙頁面加載。 而CSS也推薦寫成style標籤直接嵌在頁面上,因為如果搞個外鏈,瀏覽器需要先做域名解析,然後再建立連接,接著才是下載,這一套下來可能已經過了0.5s/1s,甚至2~3秒。而寫在頁面的CSS雖然無法緩存,但是本身它也不會很大,再加gzip壓縮,基本上在50k以內。 14. html要加上lang的屬性如下,如果是英文的網頁,應該這麼寫: 第一種表示它是英文的網頁,第二種表示它是美國英語的網頁,加上這個的好處是有利於SEO和屏幕閱讀器使用者,他可以快速地知道這個網頁是什麼語言的,如果是中文可以這麼寫:
15. 要在head標籤靠前位置寫上charset的meta標籤如下,一般charset的meta標籤要寫在head標籤後的第一個標籤: 一個原因是避免網頁顯示unicode符號時亂碼,寫在前面是因為w3c有規定,語言編碼要在html文檔的前1024個字節。如果不寫的話在老的瀏覽器會有utf-7攻擊的隱患,具體可以自行查閱資料,只是現在的瀏覽器基本都去掉了對utf-7編碼的支持了。 charset的標籤寫成html5的這種比較簡潔的寫法就行了,不需要寫成html4這種長長的: 據我所查,就算是IE6也支持那種簡短的寫法,雖然它不是一個html5瀏覽器。 16. 特殊符號使用html實體不要直接把Unicode的特殊符號直接拷到html文檔裡面,要使用它對應的實體Entity,常用的如下表所示:
特別是像©這種符號,不要從UI裡面直接拷一個unicode的字符過去,如果直接拷過去會比較醜,它取的是用的字體裡面的符號。 17. img空src的問題有時候可能你需要在寫一個空的img標籤,然後在JS裡面動態地給它賦src,所以你可能會這麼寫: 但是這樣寫會有問題,如果你寫了一個空的src,會導致瀏覽器認為src就是當前頁面鏈接,然後會再一次請求當前頁面,就跟你寫一個a標籤的href為空類似。如果是background-image也會有類似的問題。這個時候怎麼辦呢?如果你隨便寫一個不存在的url,瀏覽器會報404的錯誤。 我知道的有兩種解決方法,第一種是把src寫成about:blank,如下: 這樣它會去加載一個空白頁面,這個沒有兼容問題,不會加載當前頁面,也不會報錯。 第二種辦法是寫一個1px的透明像素的base64,如下代碼所示: 第二種可能比較符合規範,但是第一種比較簡單,並且沒有兼容性問題。 18. 關於行內元素空格和換行的影響有時候換行可能會引入空格,如下代碼: 在label和input中間會有一個空格,這樣可能會導致設置lable的width和input 的width兩者的和等於form的時候會導致input換行了,有時候你檢查半天沒查出原因,最後可能發現,原來是多了一個空格,而這個空格是換行引起的。這個時候你可能會有一個問題,為什麼<form>和<label>之間以及<input>和</form>之間的換行為什麼沒引入空格?這是因為塊級元素開始的空白文本將會被忽略,如下Chrome源碼的說明:
並且,塊級元素後面的空白文本結點將不會參與渲染,也就是說像這種: 兩個div之間有textNode的文本節點,但是不會參與渲染。 要注意的是註釋標籤也是正常的頁面標籤,也會給它創建一個相應的節點,只是它不參與渲染。 19. 類的命名使用小寫字母加中劃線連接如下使用-連接,不要使用駝峰式:
20. 不推薦使用自定義標籤是否可以使用自定義標籤,像angular那樣都是用的自定義標籤,如下代碼: 一般不推薦使用自定義標籤,angular也有開關可以控制是否要使用自定義標籤。雖然使用自定義標籤也是合法的,只要你給他display: block,它就像一個div一樣了,但是不管是從SEO還是規範化的角度,自定義標籤還是有點另類,雖然可能你會覺得它的語義化更好。 21. 重複雜id和重複屬性我們知道,如果在頁面寫了兩個一模一樣的id,那麼查DOM的時候只會取第一個,同理重複的屬性也會只取第一個,如下: 第二個class將會被忽略,className重複了又會怎麼樣?重複的也是無效的,這裡主要是注意如果你直接操作原生className要注意避免className重複,如下代碼: 如果重複執行的話,className將會有重複的valid類。 22. 不推薦使用屬性設置樣式例如,如果你要設置一個圖片的寬高,可能這麼寫: 這個在ios的safari上面是不支持的,可以自行實驗。 或者table也有一些可以設置: 但是這種能夠用CSS設置的就用CSS,但是有一個例外就是canvas的寬高需要寫在html上,如下代碼: 如果你用CSS設置的話它會變成拉伸,變得比較模糊。 23. 使用適合的標籤標籤使用上不要太單調: (1)如果內容是表格就使用table,table有自適應的優點;如果是一個列表就使用ol/ul標籤,擴展性比較好 (2)如果是輸入框就使用input,而不是寫一個p標籤,然後設置contenteditable=true,因為這個在IOS Safari上光標定位容易出現問題。如果需要做特殊效果除外 (3)如果是粗體就使用b/strong,而不是自己設置font-weight (4)如果是表單就使用form標籤,注意form裡面不能套form (5)如果是跳鏈就使用a標籤,而不是自己寫onclick跳轉。a標籤裡面不能套a標籤 (6)使用html5語義化標籤,如導航使用nav,側邊欄使用aside,頂部和尾部使用header/footer,頁面比較獨立的部分可以使用article,如用戶的評論。 (7)如果是按鈕就應該寫一個button或者<input type=」button」>,而不是寫一個a標籤設置樣式,因為使用button可以設置disabled,然後使用CSS的:disabled,還有:active等偽類使用,例如在:active的時候設置按鈕被按下去的感覺 (8)如果是標題就應該使用標題標籤h1/h2/h3,而不是自己寫一個<p class=」title」></p>,相反如果內容不是標題就不要使用標題標籤了 (9)在手機上使用select標籤,會有原生的下拉控件,手機上原生select的下拉效果體驗往往比較好,不管是IOS還是android,而使用<input type=」tel」>在手機上會彈一個電話號碼的鍵盤,<input type=」number」> <input type=」email」>都會彈相應的鍵盤 (10)如果是分隔線就使用hr標籤,而不是自己寫一個border-bottom的樣式,使用hr容易進行檢查 (11)如果是換行文本就應該使用p標籤,而不是寫br,因為p標籤可以用margin設置行間距,但是如果是長文本的話使用div,因為p標籤裡面不能有p標籤,特別是當數據是後端給的,可能會帶有p標籤,所以這時容器不能使用p標籤。 24. 不要在https的鏈接裡寫http的圖片只要https的網頁請求了一張http的圖片,就會導致瀏覽器地址欄左邊的小鎖沒有了,一般不要寫死,寫成根據當前域名的協議去加載,用//開頭:
二、CSS編碼規範1. 文件名規範文件名建議用小寫字母加中橫線的方式。為什麼呢?因為這樣可讀性比較強,看起來比較清爽,像鏈接也是用這樣的方式,例如stackoverflow的url:
或者是github的地址:
那為什麼變量名不用小寫字母加小劃線的方式,如:family_tree,而是推薦用駝峰式的familyTree?C語言就喜歡用這種方式命名變量,但是由於因為下劃線比較難敲(shift + -),所以一般用駝峰式命名變量的居多。 引入CSS文件的link可以不用帶type=」text/css」,如下代碼: 因為link裡面最重要的是rel這個屬性,可以不要type,但是不能沒有rel。 JS也是同樣道理,可以不用type,如下代碼: 沒有兼容性問題。 2. 屬性書寫順序屬性的書寫順序對於瀏覽器來說沒有區別,除了優先級覆蓋之外。但是如果順序保持一致的話,掃一眼可以很快地知道這個選擇器有什麼類型的屬性影響了它,所以一般要把比較重要的屬性放前面。比較建議的順序是這樣的: 你可能會覺得我平時差不多就是這麼寫的,那麼說明你有一個比較好的素養。並且我覺得規則不是死,有時候可以靈活,就像你可能會用transform寫居中,然後把left/top/transform挨在一起寫了,我覺得這也是無可厚非的,因為這樣可以讓人一眼看出你要幹嘛。 3. 不要使用樣式特點命名有些人可能喜歡用樣式的特點命名,例如: 然後你在它的html裡面就會看到套了大量的p1/p2/bold-font/right-wrap之類的類名,這種是不可取的,假設你搞了個red-font,下次UI要改顏色,那你寫的這個類名就沒用了,或者是在響應式裡面在右邊的排版在小屏的時候就會跑到下面去,那你取個right就沒用了。有些人先把UI整體瞄了一下,發現UI大概用了3種字號18px/16px/14px,於是寫3個類p1/p2/p3,不同的字號就套不同的類。這乍一看,好像寫得挺通用,但是當你看他的html時,你就瘋掉了,這些p1/p2/p3的類加起寫了有二三十個,密密麻麻的。我覺得如果要這樣寫的話還不如借助標題標籤如下: 因為把它的字號加大了,很可能是一個標題,所以為什麼不直接用標題標籤,不能僅僅擔心因為標題標籤會有默認樣式。 類的命名應當使用它所表示的邏輯意義,如signup-success-toast、request-demo、agent-portrait、 company-logo等等。 如果有些樣式你覺得真的特別通用,那可以把它當作一個類,如clearfix,或者有些動畫效果,有幾個地方都要用到,我覺得這種較為複雜並且通用的可以單獨作為一個類。但是還是趨向於使用意義命名。 4. 不要使用hack有些人在寫CSS的時候使用一些hack的方法註釋,如下: 這種方法的原理是由於//或者_開頭的CSS屬性瀏覽器不認識,於是就被忽略,分號是屬性終止符,從//到分號的內容都被瀏覽器忽略,但是這種註釋是不提倡的,要麼把.css文件改成.less或者.scss文件,這樣就可以愉快地用//註釋了。 還有一些專門針對特定瀏覽器的hack,如*開頭的屬性是對IE6的hack。不管怎麼樣都不要使用hack。 5. 選擇器的性能選擇器一般不要寫超過3個,有些人寫sass或者less喜歡套很多層,如下: 一個容器就套一層,一層一層地套下來,最底層套了七八層,這麼長的選擇器的性能比較差,因為Chrome裡面是用遞歸從最後一個選擇器一直匹配到第一個,選擇器越多,匹配的時間就越長,所以時間會比較長,並且代碼的可讀性也比較差,為看到最裡面的p標籤的樣式是哪個的我得一層層地往上看,看是哪裡的p。代碼裡面縮進了7、8層看起來也比較累。 一般只要寫兩三個比較重要的選擇器就好了,不用每個容器都寫進去,重要的目標元素套上class或者id。 最後一個選擇器的標籤的應該少用,因為如果你寫個.container div{}的話,那麼頁面上所有的div第一次都匹配中,因為它是從右往左匹配的,這樣的寫的好處是html不用套很多的類,但是擴展性不好,所以不要輕易這樣用,如果要用需要仔細考慮,如果合適才使用,最起碼不能濫用。 6. 避免選擇器誤選有時候會出現自己的樣式受到其他人樣式的影響,或者自己的樣式不小心影響了別人,有可能是因為類的命名和別人一樣,還有可能是選擇器寫的範圍太廣,例如有人在他自己的頁面寫了: 結果導致在他個頁面的公用彈框樣式掛了。一方面不要寫*全局匹配選擇器,不管從性能還是影響範圍來說都太大了,例如在一個有3個子選擇器的選擇器: 在三個容器裡面,*都是適用的,並且有些屬性是會繼承的,像font-size,會導致這三個容器都有font-size,然後一層層地覆蓋。 還有一種情況是濫用了:first-child、:nth-of-type這種選擇器,使用這種選擇器的後果是擴展性不好,只要html改了,就會導致樣式不管用了,或者影響到了其它無關元素。但是並不是說這種選擇器就不能用,只要用得好還是挺方便的,例如說在所有的li裡面要讓最後一個li的margin-left小一點,那麼可以這麼寫: 這可能比你直接套一個類強。但是不管怎麼樣,不能濫用,合適的時候才使用,而不是僅僅為了少寫類名。 7. 減少覆蓋覆蓋是一種常用的策略,也是一種不太優雅的方式,如下代碼,為了讓每個house中間的20px的間距,但是第一個house不要有間距:
其實可以改成這樣: 只有前面有.house的.house才能命中這個選擇器,由於第一個.house前面沒有,所以命不中,這樣看起來代碼就簡潔多了。 還有這種情況,如下代碼所示: 其實可以借助一個:not選擇器: 這樣看起來代碼也優雅了很多。 有一種覆蓋是值得的,那就是響應式裡面小屏的樣式覆蓋大屏,如下: 大屏的樣式也可以寫成: 我一開始是就是這麼寫的,為了遵循減少覆蓋原則,但是後來發現這種實踐不好,代碼容易亂,寫成覆蓋的好處在於可以在瀏覽器明顯地看到,小屏的樣式是覆蓋了哪個大屏的樣式,這個在大屏的時候又是怎麼樣的。 8. 使用CSS3的選擇器完成一些高級的功能上面提到:not可以讓代碼簡潔,還有其它一些很好用的。例如說只有兩個的時候一個佔比50%,而有3個的時候一個佔比33%,這個用CSS就可以實現,如下: 當li是第一個元素並且是倒數第二個元素的時候以及和它相鄰的li被第二組選擇器命中,它的寬度是50%,也就是只有兩個li的時候才能滿足這個條件。 另外還可以借用:hover/:focus/:invalid/:disabled等偽類選擇器完成一些簡單的交互。 9. 少用!importantimportant用來覆蓋屬性,特別是在CSS裡面用來覆蓋style裡的屬性,但是important還是少用為妙。有時候你為了偷懶直接寫個!important,以為這個的優先級是最高的了,往往螳螂捕蟬,黃雀在後,很可能過不了多久又要再寫一個優先級更高的覆蓋掉,這樣就略顯尷尬了。所以能少用還是少用。如果要覆蓋還是先通過增加添加選擇器權重的方式。 10. 多寫註釋「程序猿最煩兩件事,第一件事是別人要他給自己的代碼寫文檔,第二件呢?是別人的程序沒有留下文檔」。註釋也是同樣道理,當看到很多綠色的註釋代碼神經會比較放鬆,而當看到揉成一團還沒有註釋的代碼是比較壓抑的。CSS的註釋可包括: (1)文件頂部的註釋
(2)模塊的註釋
(3)簡單註釋
(4)TODO的註釋有時候你看源碼的時候你會看到一些TODO的註釋: 表示這些代碼還有待完善,或者有些缺陷需要以後修復。而這種TODO的註釋一般編輯器會把TODO高亮。 注意不要寫一些錯誤的誤導的註釋或者比較廢話的註釋,這種還不如不寫,如下:
11. 排版規範不管是JS/CSS,縮進都調成4個空格,如果你用的sublime,在軟件的右下角有一個Tab Size,選擇Tab Size 4,然後再把最上面的Indent Using Spaces勾上,這樣,當你打一個tab鍵縮進的時候就會自動轉換成4個空格。如果你使用vim,新增或者編輯~/.vimrc文件新增一行: 也會自動把縮進改成4個空格,其它編輯器自行查找設置方法。因為\t在不同的編輯器上顯示長度不一樣,而改成空格可以在不同人的電腦上格式保持一致。 多個選擇器共用一個樣式集,每個選擇器要各佔一行,如下: 每個屬性名字冒號後面要帶個空格,~、>、+選擇器的前後也要帶一個空格:
12. 屬性值規範(1)如果值是0,通常都不用帶單位例如: 應改成: 但是有個特例,就是和時間有關的時間單位都要帶上秒s,如下兩個都是不合法的:
(2)色值用十六進制,少用rgb如下: 應改成: 因為使用rgb是一個函數,它還要計算一下轉換。如果是帶有透明度的再用rgba. 如果色值的六個數字一樣,那麼寫3個就好:
(3)注意border none和0的區別如下兩個意思一樣: 而下面這兩個一樣: 所以用0和none都可以去掉邊框。 你可能會說打包工具其實最後會幫我處理,但自己要保持一個良好的書寫習慣還是很重要的。 13. font-family的設置注意使用系統字體的對應的font-family名稱,如SFUIText Font這個字體,在Safari是-apple-system,而在Chrome是BlinkMacSystemFont,所以font-family可以這麼寫: 再如微軟雅黑,很多中文網站都用這個字體,要寫成: 另外font-family不能在代碼任意設置,如果使用了自定義字體。如下代碼: 因為如果你在代碼裡面寫了好多個font-family,到時候要整體替換網頁的字體就很麻煩了,正確的做法應該是這樣的: 如果需要加粗就用標題標籤,或者b/strong標籤,並且要把font-weight調回來,因為那個字體本身就有加粗效果了,如果font-weight再是粗體的話瀏覽器會用自己的算法繼續加粗。如果是細體怎麼辦,一方面一般細體用得比較少,另一方面沒有細體的標籤,可以通過套類的方式。 14. 不要設置太大的z-index有些人喜歡設置z-index很大: 以為他是老大了,不會有人再比他高了,但是螳螂捕蟬,黃雀在後,很快得再寫一個: 通常自己頁面的業務邏輯的z-index應該保持在個位數就好了。 15. 合併屬性一般的說法是說為了提高性能,屬性要合併,但其實Chrome每個屬性都是單獨的,就算你合在一起,它也會幫你拆出來,如把margin拆成left/right/top/bottom,但是我們還是推薦寫成合的,因為它可以讓代碼看起來更簡潔,代碼量更少,如下代碼: 可以寫成: 但是合在一起寫了,要注意別覆蓋了其它的設置,如上面把margin-bottom設置成了0. 再如: 可以改成:
16. 注意float/absolute/fixed定位會強制設置成block如下代碼: 第二行的display: block其實是沒用的,因為如果你浮動了,目標元素就會具有塊級盒模型的特性,即使你display: table-cell或者inline也不管用。如果你是display: flex,那麼float將會被忽略。 同樣地,absolute定位和fixed定位也有同樣的效果,會把行內元素變成塊級的。 17. 清除浮動清除浮動有多種方法,一般用clearfix大法,雖然這個方法有缺陷,但是它比較簡單且能夠適用絕大多數的場景,一個兼容IE8及以上的clearfix的寫法: 就不要在末尾添加一個多餘元素的方法清除浮動了,雖然也可行,但是比較low. 18. 引號的使用(1)font-family一般來說font-family不需要添加引號,即使字體名稱帶有空格也沒關係,但是有一種情況是一定要加上引號的,就是字體名稱剛好是關鍵詞,如下字體都需要加關鍵詞:
(2)background的url
你不加也可以,但是有一種一定要加,那就是url裡面帶有特殊字符沒有轉義,如下: 上面瀏覽器會去加載//cdn.test.me/hello,然後報404。這種情況通常是圖片是用戶上傳的,圖片的名字帶有空格,後端給的url沒有對特殊字符做處理,就會有問題,所以當url是可變的時候,最好還是帶上引號: 這樣瀏覽器就能正常加載圖片了。這種情況最好的還是從源頭上避免,但我們也可以做個兼容。 (3)單引號還是雙引號這兩個都是合法的,只是統一一下比較好,不能一下子單引號,一下子雙引號的,比較普遍的推薦是html使用雙引號,css使用單引號。 19. CSS動畫規範(1)不要使用all屬性做動畫 使用transition做動畫的時候不要使用all所有屬性,在有一些瀏覽器上面可能會有一些問題,如下: 在Safari上面可能會有一些奇怪的抖動,正確的做法是要用哪個屬性做動畫就寫哪個,如果有多個就用隔開,如下代碼所示:
(2)使用transform替代position做動畫如果能用transform做動畫的,就不會使用left/top/margin等,因為transform不會造成重繪,性能要比position那些高很多,特別是在移動端的時候效果比較明顯。基本上位移的動畫都能用transform完成,不需要使用CSS2的屬性,如一個框從右到左彈出。 (3)偏向於使用CSS動畫替代JS動畫例如把一個框,從下到上彈出,可以用jQuery的slideUp函數,或者自己寫setInterval函數處理,但是這些沒有比用CSS來得好。使用CSS,初始狀態可以把框translate移動屏幕外,然後點擊的時候加上一個類,這個類的transform值為0,然後再用transition做動畫就好了。 20. 不要斷詞英文的單詞或者數字如果當前行排不下會自動切到下一行,這樣就導致每行長短不一,有時候可能不太美觀,但是不能使用word-break: break-all把一個單詞拆成兩行,還有一種是使用: 它會把單詞拆成用-連接的形式,看起來好像挺合理,但是由於它斷詞斷得不夠徹底,有些單詞斷不了,長短不一的現象看起來也比較明顯,有些單詞還被拆成了兩行,所以還不如不加。 因此,不要使用斷詞。 21. 不要設置圖標字體font-family這個和上面提到的font-family設置是一樣的,不要在代碼裡面手動設置font-family,如下: 正確的做法是給.icon-up的元素再套一個.icon的類,font-family等對圖標字體的相關設置都統一在這個類裡面: 因為我們可能會添加其它一些設置,有個.icon的類統一處理比較好。就不要手動一個個去設置font-family了。 22. 設置常見樣式reset由於每個瀏覽器都有自己的UA樣式,並且這些樣式還不太統一,所以需要做樣式reset,常見的reset有以下:
23. 圖片壓縮不管是UI直接給的圖片還是自己從UI圖裡切出來的圖片,都需要把圖片壓縮一下,建議使用tinypng,它可以在保持圖片質量減少較低的情況下,把圖片壓得很厲害,比直接在PS裡面設置壓縮質量要強。如果是色彩比較豐富的圖片要使用jpg格式,不能使用png格式,png會大得多,如果是logo那種矢量圖片,直接使用svg格式即可。一般來說要把圖片控制在300k以內,特別是banner頭圖,圖片的大小也要控制住。 24. 正確使用background和img顯示一張圖片有兩種方式,可以通過設置CSS的background-image,或者是使用img標籤,究竟什麼時候用哪種呢? 如果是頭圖等直接展示的圖片還是要img標籤,如果是做為背景圖就使用background,因為使用img可以寫個alt屬性增強SEO,而背景圖那種本身不需要SEO。雖然background有一個一個background-position: center center很好,但是頭圖那種還是使用img吧,自己去居中吧,不然做不了SEO。 25. 響應式的規範響應式開發最不好不要雜合使用rem,文字字號要麼全部使用rem,要麼不要用,也不要使用transform: scale去縮小,因為被縮小的字號看起來會有點奇怪,別人都是14px,而你變成了13.231px,小了一點。響應式的原則一般是保持中間或者兩邊間距不變,然後縮小主體內容的寬度。 26. 適當使用:before/:after:before和:after可以用來畫頁面的一些視覺上的輔助性元素,如三角形、短的分隔線、短豎線等,可以減少頁面上沒有用的標籤。但是頁面上正常的文本等元素還是不要用before/after畫了。 27. 少用absolute定位首先absolute定位的元素渲染性能會比較高,因為它獨立出來了,計算量會少,用得好還是可以的。但是如果你頁面的主要佈局是使用absolute的那肯定是不可取的,因為absolute定位的可擴展性很差,你把每個元素的位置都定死了就變不了了,可以多用float,雖然float的性能相對較差,但是不管是實用性還是兼容性都是挺好的。 28. 少用inline-block佈局有些人喜歡用inline-block,特別是剛開始學切圖的人,因為block會換行,而inline-block不會換行還具有盒模型,因此inline-block用得很順手,而float比較複雜,還要處理清除浮動之類的問題。如下佈局: 應該寫li,然後讓li float,如果你讓li display:inline-block也可以達到目的。但是inline-block用得多了可能會有一些奇怪的問題,你通常要在一個inline-block的元素裡面套block的元素,inline-block是行內元素,而block是塊級元素,這兩者終究有點差別。這種應該用float/flex會更自然,如果你float用順手了你會發現比inline-block好多了,並且更加專業。如果你沒怎麼用過flex ,那你可以嘗試換一下使用flex,如果你沒怎麼用過float,可以嘗試用一下。只有你的切圖方式多樣化了,你切起圖來才能比較靈活。 29. 圖片的居中和寬高設定一般來說,UI給的圖片展示寬高是固定的,但是實際的圖片長寬是不固定,大部分圖片是長是比寬大,小部分圖片是寬比長大。所以需要居中裁剪展示,如下圖所示: 中間黑色的框是展示區域,圖片的短邊和窗器的邊一樣大,另一邊按圖片的原始比例拉伸,然後居中顯示。這個得借助JS,因為圖片未加載好之前,不知道是長邊比較大還是寬比較大。如下代碼: 借助一個resizeImg函數,在onload函數裡面做處理。然後居中用CSS: 上面代碼用了一個margin: auto做居中。 30. 移動端提高可點區域範圍移動端的的一些圖標如X,可能會設計得比較小,所以點起來會不太好點,因此要提高可點區域範圍,可通過增加padding,如下代碼: 這樣區域就增加了一圈,點起來就容易多了。 31. 不要設置input的line-height如果設置input的line-height,如下代碼,你可能要做垂直居中: 設置了line-height為一個很高的值,這樣會導致Safari瀏覽器的輸入光標|變得巨大,所以如果你要居中的話,使用padding吧。 32. 移動端彈框要禁止body滑動因為IOS Safari切換輸入框的時候會頁面會彈閃得很厲害,因為你在切的時候它會先把鍵盤收起來,然後再彈出來,這個時間很短,給人感覺頁面彈閃了一下,但如果把body禁止滑動了就不會有這個問題,這有兩個解決辦法,第一種是把body fixed住,第二種設置body overflow: hidden,相對來說第二種比較簡單一點。IOS10完全不會閃,IOS9以下還是會閃。 33. 對於漸變的處理有時候UI裡面會有一些漸變的效果,無法複製CSS出來,這個時候可以用一個在線的工具,生成漸變的CSS:http://www./gradient-generator#,但是這個需要自己手動調一個和UI一模一樣的效果,或者可以直接給UI調一個它理想的效果,它會生成兼容性很強的CSS:
34. 行內元素可以直接設置margin-left/margin-right如下有些人為了把span撐開,設置span display: inline-block: 其實行內元素可直接margin的左右,能夠把它撐開,不需要設置inline-block: 另外需要注意的是img/input/textarea/button默認就是inline-block,也不用再設置。 三、JS編碼規範1. 變量命名《代碼大全》這本書裡面有一章是專門講變量命名的,這裡結合這本書的建議做說明。總地來說,變量名要準確完整地描述該變量所表述的事物,具體來說: (1)變量名不應以短巧為榮如以下好的變量名和不好的變量名:
左邊的變量名都不太清楚,代碼的擴展性不好,一旦代碼需要加功能的話,就容易出現obj1、obj2、obj3這種很抽象的命名方式。所以一開始就要把變量的名字起得真實有意義,不要搞一些很短很通用的名字。 當然變量名取得太長也不好,如maximumNumberOfTeamMembers. (2)變量名不要使用計算機術語變量名應直指問題領域,來源於現實世界,而不是計算機世界,例如取了texareaData之類的名字,應該取一個和業務相關的名字,如leaveMsg. (3)變量名的對仗要明確如up/down、begin/end、opened/closed、visible/invisible、scource/target,對仗明確可以讓人很清楚地知道兩個變量的意義和用途。 (4)警惕臨時變量有些喜歡取temp和obj之類的變量,如果這種臨時變量在兩行代碼內就用完了,接下來的代碼就不會再用了,還是可以接受的,如交換數組的兩個元素。但是有些人取了個temp,接下來十幾行代碼都用到了這個temp,這個就讓人很困惑了。所以應該儘量少用temp類的變量,如下代碼: 應改成:
(5)bool變量《代碼大全》這本書建議布爾變量不用以is/do之類的開頭,如: 可改成: 還有其它一些常用的名稱如done/found/successs/ok/available/complete等,結合具體的語境: 另外變量名不要使用否定的名詞,如notOk,notReady,因為否定的詞取反的時候就會比較奇怪,如if(!notOk). 要使用肯定的布爾變量名。如果是參數的話可結合ES6的默認形參值。 (6)變量名使用正確的語法 不要使用中文拼音,如shijianchuo應改成timestamp,如果是複數的話加s,或者加上List,如orderList、menuItems,而過去式的加上ed,如updated/found等,如果正在進行的加上ing,如calling. 2. 聲明變量時要賦值如下聲明三個變量: 以上絕對是合法JS語法,但是這三個變量的用途會讓人比較困惑,特別是中間第二個question,問題是什麼。但是當你把上面的變量賦一個初始值的時候: 就讓人豁然開朗了,原來question是一個問題的字符串,而result是一個數字,form是一個對象。這也有利於JS解釋器提前做一些優化處理,不用等到使用的時候才知道這些變量是什麼類型的。 3. 函數的返回值類型要確定如下代碼: 這個代碼可能返回整型,也有可能返回字符串,就會讓人比較困惑,同時從代碼性能來說也是不高的,雖然它是合法的JS語法,一個函數的返回類型要統一。你可能會說我用上面的函數做為輸入框顯示的值,如果是負數或者0,那麼輸入框就不要顯示任何東西,所以才會返回空的字符串。即使是這樣的原因也不建議這樣寫,從長遠來看這樣寫是不利的,你應該用其它的方法組織你的代碼。要養成強類型的代碼風格,這樣不容易出bug,擴展也容易。另外如果一個變量你把它當成數字使用,下面就不要再把它當成字符串使用了,因為這樣也容易讓人困惑。微軟的Typescript就是一種強類型的書寫語法,很多大型項目會使用typescript寫JS,有興趣的可以繼續瞭解怎麼寫typescript. 4. 不要給變量賦值undefinedundefined表示一個變量未定義,你定義了一個變量又說它未定義本身就很奇怪。這可能會造成的問題是使用上的歧義,因為我們經常使用undefined來判斷變量有沒有定義: 如果要賦值應該要賦空值,如對象賦值為null,數字賦值為0,字符串賦值為空字符,那你可能會說0也是一個正常的數字,如果賦值為0會導致我誤認為它是一個正常的數據,那怎麼辦呢?如果你的數字都是非負數,那麼可以把初始值置為-1,實在不行就置成NaN. 函數的返回值也不要顯式地return undefined. 5. 排版規範一個比較流行的空格和縮進排版如下代碼所示: 一行太長要換行,如V8的源碼裡面一行最長是70個字符,超過就換行: 一行代碼太長了就換行是一種好的習慣,太長讓人看起來比較費勁。基本上一行不要超過100個字符,超過就要換行,不管是註釋還是代碼。 6. 使用===代替====會帶上類型轉換,這和上面一樣的,我們要用強類型的風格寫代碼,所以不要使用==,如果有類型轉換自己做類型轉換,不要讓別人去猜這裡面有類型轉換,使用==會有一些比較奇怪的結果:
7. 減少魔數對一些比較重要的常量起一個名字,例如下面的代碼: 再如下面不好的寫法: 上面四個常量會讓人看起來比較困惑,如果可以的話給它們起個名字,如果覺得麻煩那就加上註釋。 8. 不要讓代碼暴露在全局作用域下運行一個原因是在全局作用域下,變量的查找時間會更長,第二個原因是污染全局作用域,有時候會造成一些意想不到的結果,如下: 定義了一個變量,但是剛好不巧window.name是本來有這個屬性,這個屬性通常用來跨域傳遞數據。如果你設置了name這個變量,就把全局的window.name給覆蓋了。 9. let/var/const的使用ES6新增了let/const定義變量,使用let有一些好處,如: (1)避免變量重複定義
使用babel loader打包的時候它會做靜態檢查:
(2)for循環的變量作用域是獨立的
使用let使得i在for循環裡面每次運行的作用域都是獨立的。並且for裡定義的變量在for循環外是不可見的。 babel在轉換的時候,會在for循環裡面套一個function,然後把i當作函數的參數: 由於let可以避免變量重複定義,就衝著這一點,就使得它很有意義。所以推薦多用let定義變量。所以本規範下面的變量將使用let代替var. 而const適合於給常量起個名字,如上面提到的: 或者是定義其它一些不需要修改的變量,防止不小心被其它代碼修改了。 10. 簡潔代碼(1)使用三目運算代替簡單的if-else可以寫一行就不要寫三行,如下: 可以改成三目運算符: 代碼從8行減少到了2行。 (2)使用箭頭函數取代簡單的函數例如以下代碼: 可改成: 代碼從3行變成了1行。 11. 注意避免執行過長時間的JS代碼對於一般的頁面的數據量來說,加減乘除等計算不足以造成性能瓶頸。容易造成瓶頸的是DOM操作,特別是大批量的DOM操作,只要一次有幾百上千的級別就容易造成頁面卡頓。特別是不要在一個for循環裡不斷地修改DOM,如下代碼: 這種可以先把li拼好了,再一次性append到ul裡面,如下代碼: 如果你用jq的話應該先把模板渲染好,然後再一次性append到dom裡面,而不是不斷地append到dom裡面。現在的瀏覽器一般也比較智能,它會做一些優化,但是我們不能老是指望瀏覽器會優化。 但是還是要注意數據量特別大的情況,你可能要使用setTimeout的方式分段處理數據,甚至使用多線程。使用setTimeout可以這樣: 我們使用一個遞歸,把數據分段處理,每段100個,當數據處理完再調完成回調函數。 12. 多寫註釋這個和CSS規範類似: (1)文件頂部的註釋,包括描述、作者、更新
(2)函數的註釋
上面的@auhor @return都是註釋標籤,其它常用的註釋標籤還有:
(3)變量定義和代碼的註釋對一些比較重要的變量加註釋,標明它是什麼用途,以及對一些核心代碼邏輯加上註釋,或者比較複雜的業務邏輯,寫了5個case,每個case分別代表什麼;為了改某個bug而加入的代碼,說明下為瞭解決什麼問題;還有某些易混的判斷,為什麼if判斷條件寫了四個,為什麼代碼到這個if判斷不通過就直接return了;一些常量的註釋,為什麼會突然冒出來100這個數字;改動了別人的代碼,為什麼要改動;等等。如: 總之多寫註釋還是好的,只要不是廢話: 或者是和邏輯不符合的錯誤註釋。 還有一種排版的註釋,右括號的對應關係: 主要是為了方便在後面加代碼,例如我要在switch(b)後面加代碼,當我看到這個註釋我就很清楚地知道需要在哪裡按回車。不過一般不推薦嵌套很深的代碼,或者寫得很長,一個函數幾百行。 13. 代碼不要嵌套太深有些人的代碼經常會套個七八層,以jq代碼為例,如下: 上面的代碼最深的一層縮進了八層,你可能會覺得這樣邏輯挺清晰的啊,但是這種寫法同時也有點面條式。以上代碼如果讓我寫,我會這麼組織: 首先把綁定的匿名函數改成有名的函數,這樣有個好處,當你想要off掉的時候隨時可off掉,然後可以減少一層縮進,接著把根據orderStatus不同的回調先用變量判斷好,而不是同時積壓到後面再一起處理。再把發送請求的函數再單獨抽出來做為一個函數,這樣可以減少兩層縮進。上面最深的縮進為4層,減少了一半。並且你會發現這樣寫代碼邏輯會更加清晰,我在bindEvent裡面掃一眼就可以知道哪些DOM綁了哪些事件,然後我對如對哪個DOM的事件感興趣再跳到相應的回調函數去看,而不用拉了一兩頁才在bindEvent裡面找到目標DOM。並且把updateOrder單獨做為一個獨立的函數,其它地方如果需要也可以使用,例如可能還有一個組合功能的操作可能會用到。另外把ajax再做一層抽象主要是這個東西實在是太常用,讓人一眼就知道要幹嘛,把它分離到另外一個地方可以讓具體的業務代碼更加簡單,例如上面發請求,我把回調函數準備好之後,只要執行一行代碼就好了。 你縮進太多層,一行就被空格佔掉了三、四十個字符,感觀上就不是很好,還會出現上面提到的,最後面要寫好多個右括號收尾的情況,並且一個函數動不動就兩、三百行。 14. jQuery編碼規範如果你使用了jQuery。 (1)使用closest代替parent儘量不要使用parent去獲取DOM元素,如下代碼: 這樣的代碼擴展性不好,一旦DOM結構發生改變,這裡的邏輯分分鐘會掛,如某天你可能會套了個div用來清除浮動,但是沒想到導致有個按鈕點不了了就坑爹了。 應該用closest,如: 直接定位和目標元素的最近共同祖先節點,然後find一下目標元素就好了,這樣就不會出現上面的問題,只要容器的類沒有變。如果你需要處理非自己的相鄰元素,可以這麼搞: 有時候你可以先把所有的li都置成某個類,然後再把自己改回去也是可取的,因為瀏覽器會進行優化,不會一見到DOM操作就立刻執行,會先排成一個隊列,然後再一起處理,所以實際的DOM操作對自己先加一個類然後再去掉的正負相抵操作很可能是不會執行的。 (2)選擇器的性能問題如下代碼: 上面的代碼做了三個全局查找,其實可以優化一下: 先做一個全局查找,後續的查DOM都縮小到$page的範圍,$page的節點只有幾十個,在幾個裡面找就比在document幾百幾千個節點裡面查找要快多了。jQuery的查DOM也是用的querySelectorAll,這個函數除了用在document之外,可用在其它DOM結點。 (3)on事件之前需要的時候才off有些人喜歡在綁事件之前先off掉,這樣感覺可以確保萬無一失,但是如果你綁的事件是匿名的,你很可能會把其它JS文件綁的一起off掉了,並且這樣不容易暴露問題,有時候你的問題可能是重複綁定事件,如點一次按鈕就綁一次就導致了綁多次,所以根本原因在這裡。你應該要確保事件只被綁一次,而不是確保每次寫之前都先off掉。如果你的事件容易出現綁多次的情況說明你的代碼組織有問題,這個在開發的時候應該是能夠暴露出來的。 (4)對DOM節點較少的不要使用委託例如說一個表單只有幾個input元素,然後你給input加了個委託到form上面,甚至有時候是body上面,由於事件冒泡導致在form上或者在頁面上的所有操作都會冒泡到form/body上,即使操作的不是目標元素,這樣jQuery就會收到在body上的事件,然後再判斷處理所有的操作的目標元素是不是你指定的那個,如果是再觸發你綁的回調函數。特別是像mousemove觸發得頻繁的事件都需要執行。所以如果元素比較少或者不需要動態增刪的那種就不要使用冒泡了,直接綁在對應的多個元素就好了。 (5)有時候使用原生更簡單例如獲取表單的input的和它的value: 如果form裡面有一個input[name=email]的輸入框,就可以這麼用。 再如,改變一個button的狀態,下面兩個其實差不多,但是如果獲取不到dom元素的話第一個會掛: 設置一個元素的display為block: 但是絕大多數的情況下還是要使用jq的API以確保兼容性,如下獲取scrollTop: 因為在firefox裡面需要使用: 而這個在Chrome永遠返回0。再如window.innerWidth在某些低版本的安卓手機會有問題。所以當你不確定兼容性的時候,就不要使用原生API,不然你得經過小心驗證後再使用。你可以不用,但不是說不要去瞭解原生API,多去瞭解原生DOM操作還是挺有幫助的。 15. 對於常用的屬性進行緩存如下代碼,頻繁地使用了window.location這個屬性: 可以先把它緩存一下,加快變量作用域查找: 當把location變成一個局部變量之後,它的查找時間將明顯快於全局變量。你可能會說就算再快這點時間對於用戶來說還是沒有區別的吧,但是這是做為一名程序員的追求,以及可以讓代碼更簡潔。 16. 儘量不要在JS裡面寫CSS如下代碼,如果是非選中狀態就把顏色置灰: 反之顏色恢復正常: 這樣的代碼有問題,如果以後顏色改了,那麼你需要改兩個地方,一個是CSS裡設置,另一個是JS裡面設置,而JS寫的樣式特別容易被忽略,查起來也不好定位。好的做法應該是通過添加刪除類的方法: 然後再通過CSS給selected的類添加樣式。如果是button之類的控件可以結合:disabled、:checked、:valid等偽類,連類都不用添加 但是有一種是一定要用JS控制的,就是需要先計算然後動態地改變position或者transform的值,如果用CSS3的transition實現不了. 17. 在必要的地方添加非空判斷添加非空判斷可以提高代碼的穩健性,如下代碼: 如果傳的為空就不用處理,有時候你可能要拋個異常,告訴調用者。對一些比較重要的地方可能還要添加類型檢驗。後端傳的數據要確保會有那個屬性,如果不確定也要添加非空判斷。如果調了第三方的API,添加出錯處理也很重要,因為你不能確保第三方API一定能正常工作,在一些你覺得可能會掛的地方做處理,如請求可能會超時,或者返回了undefined的異常結果,這種多使用一般能夠發現。 18. 不要用for in循環數組如下代碼: 正常情況下將會輸出數組的元素,但是很不幸的是,如果有人給數組原型添加了一個函數: 循環裡的i將會有4個值:0, 1, 2, 「add」,這樣就導致你的遍歷出現問題,所以數組遍歷應該使用length屬性或者數組的forEach/map方法。 19. 分號規範JS裡面的表達式是可以不用分號結尾,例如Zepto的源碼幾乎沒看到一個分號,但是我們還是提倡要每個句子後面都要加上分號,這樣不容易出錯。 20. 使用location跳轉需要先轉義對於那些根據用戶輸入內容做跳轉,需要先把用戶內容做轉義,如下有問題的代碼: 如果用戶輸入了一個#號如門牌號,將會導致#後面的內容當作錨點了,或者用戶可能會輸入一個空格。所以如果不確定內容的東西需要先encode一下,如下代碼: 這樣跳轉就沒有問題了。 21. 點擊跳轉儘量不要使用onclick跳轉點擊一個容器的時候做跳轉,有些人喜歡這麼寫: 其實這樣寫不好,不利於SEO,如果是一個跳轉應該用a標籤,如下: 同時把a標籤變成塊級。就算你不用做SEO,也應當儘量使用這種方式,因為用這種方式比較自然,還可以控制是否要新開頁,如果在移動端也不用考慮click事件是否有延遲的問題。 22. 不要直接使用localStorage由於Safari的隱身模式下本地存儲會被禁用,如果你嘗試往localStorage寫數據的話,會報超出使用限制的錯誤:
而Chrome的隱身窗口不會禁用。而使用Safari的用戶可能會開隱身窗口,特別是手機上的。這樣就導致代碼拋異常了,所以為了兼容Safari,不能直接使用localStorage,要做個兼容: 上面代碼做了個兼容,如果不支持localStorage就使用cookie。要注意cookie一個域名最多只能有4kB,50個key,而本地存儲限制為5Mb. 23. 使用簡便的轉換(1)把字符串轉整型可以使用+號
+號相當於Number: parseInt和Number有一個很大的區別是parseInt(「10px」)結果為10,而Number(「10px」)是NaN,parseInt會更加自然,其它編程語言也有類似的轉換。但是Number還是能適用很多的場景。 (2)把小數去掉尾數轉成整型,可以使用 >> 0如果計算某個數字在第幾排: 都可改成: 這個用位運算的效率會明顯高於上面兩個。 (3)轉成boolean值用!!如下代碼:
24. 注意返回false的變量有幾個值在if判斷裡面都返回false:0、false、」」、undefined、null、NaN都是false,所以判斷一個數組有沒有元素可以這麼寫: 而不用寫成: 判斷一個字符串是不是空可以寫成: 但是判斷一個變量有沒有定義還是要寫成: 因為如果直接if變量的話,上面的幾個可能取值都將認為是沒定義。 25. 使用Object.assgin簡化數據賦值如下代碼,在發請求之前,經常需要獲取表單的值,然後去修改和添加老數據提交: 其實有一種更優雅的方式那就是使用Object.assign: 使用這個的好處是可以弄一個setOrderData的Object,寫成大括號的形式,而不用一個個去賦值,寫起來和看起來都比較累。最後再assign一下賦值給原先的Object就可以了。 26. 調試完去掉無關的console調試完就把console.log之類的打印信息去掉,別想著等一下做完了再刪,等一下就忘了。另外,不要使用alert調試,console/debugger上線了都沒事,一般用戶也不會開一個控制台,但是alert上線了就完蛋了,特別是有些人喜歡用alert(「fuck」)之類的看下代碼有沒有運行到這裡,這種調試技巧還是比較初級,要是真上線了可能得捲鋪蓋走人了。這也可以通過代碼檢查工具做靜態檢查。 27. 注意this的指向如下代碼: 當觸發searchBtn的點擊事件時,search函數裡的this已經指向 searchBtn了,因為它是click的回調函數: 所以函數運行環境就變成了btn了,因此這種單例的Object最好不要使用this,應直接使用當前命名空間的變量名: 這樣就沒問題了。 28. 使用正則表達式做字符串處理正則表達式可以很方便地處理字符串,通常只要一行代碼就搞定了。例如去掉全局的某一個字符,如去掉電話號碼的-連接符: 或者反過來,把電話號碼改成3-3-4的形式: 熟練掌握正則表達式是每個前端的基本技能。 29. 保持復用模塊的觀念當你一個函數要寫得很長的時候,例如兩、三百行,這個時候你考慮把這個大函數給拆了,拆成幾個小函數,然後讓主函數的邏輯變得清晰簡潔,而每個小函數的功能單一獨立,使用者只需要管輸入輸出,而不需要關心內部是怎麼運行的。如下在地圖裡面處理用戶點擊的處理函數: 上面拆成了很多個小函數,如畫點的drawPoint函數,使用這個函數只需要關心給它一個當前點的經緯度就可以了,它就幫你畫一個點。 在函數之上又可以繼續抽象,如把這個畫圖功能的模塊寫成一個DrawTool的類,這個類負責整個畫圖的功能,使用者只需要實例化一個對象,然後調一下init,傳一些參數就好了。 先抽成不同的函數,每個函數負責一小塊,相似的函數聚集在一起形成一個模塊,幾個模塊的相互調用又形成一個插件。 30. 注意label事件會觸發兩次如果label裡面有input,監聽label的事件會觸發兩次,如下代碼: 當點到span的時候,click事件會觸發兩次,如果label裡面沒有input的話,就只會觸發一次。這是為什麼呢?因為在label容器內,點到span文字的時候會下發一次click事件給input,input事件又會冒泡到label,因此label會觸發兩次。因此如果你直接監聽label事件要注意注意觸發兩次的情況。 |
|