狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
版主

不唐突的JavaScript的七條準(zhǔn)則

tercel
2011年3月25日 11:33 本文熱度 3690
英文原文:The seven rules of Unobtrusive JavaScript
原文作者:Chris Heilmann

經(jīng)過多年的開發(fā)、教學(xué)和編寫不唐突的JavaScript, 我發(fā)現(xiàn)了下面的一些準(zhǔn)則。我希望它們可以幫助你對“為什么這樣設(shè)計和執(zhí)行JavaScript比較好”有一點理解。這些規(guī)則曾經(jīng)幫助我更快地交付產(chǎn)品,并且產(chǎn)品的質(zhì)量更高,也更容易維護(hù)。

1.不要做任何假設(shè)
(JavaScript是一個不可靠的助手)

可能不唐突的JavaScript 的最重要的一個特性就是——你要停止任何假設(shè):

    * 不要假設(shè)JavaScript是可用的,你最好認(rèn)為它很有可能是不可用的,而不是直接依賴于它。
    * 在你經(jīng)過測試確認(rèn)一些方法和屬性可以使用之前,不要假設(shè)瀏覽器支持它們。
    * 不要假設(shè)HTML代碼如你想象的那樣正確,每次都要進(jìn)行檢查,并且當(dāng)其不可用的時候就什么也不要做。
    * 讓JavaScript的功能獨立于輸入設(shè)備
    * 要記住其他的腳本可能會影響你的JavaScript的功能,所以要保證你的腳本的作用域盡可能地安全。

在開始設(shè)計你的腳本之前,要考慮的第一件事情就是檢查一下你要為其編寫腳本的HTML代碼,看看有什么東西可以幫助你達(dá)到目的。

2.找出鉤子和節(jié)點關(guān)系
(HTML是腳本的基石)

在開始編寫腳本之前,要先看一下你要為之編寫JavaScript的HTML。如果HTML是未經(jīng)組織的或者未知的,那么你幾乎不可能有一個好的腳本編寫方案——很可能就會出現(xiàn)下面的情況:要么是會用JavaScript創(chuàng)建太多標(biāo)記,要么就是應(yīng)用太依賴于JavaScript。

在HTML中有一些東西需要考慮,那就是鉤子和節(jié)點關(guān)系。

<1>.HTML 鉤子

HTML最初的和最重要的鉤子就是ID,而且ID可以通過最快的DOM方法——getElementById 訪問到。如果在一個有效的HTML文檔中所有的ID都是獨一無二的話(在IE中關(guān)于name 和 ID 有一個bug,不過有些好的類庫解決了這個問題),使用ID就是安全可靠的,并且易于測試。

其他一些鉤子就是是HTML元素和CSS類,HTML元素可以通過getElementsByTagName方法訪問,而在多數(shù)瀏覽器中都還不能通過原生的DOM方法來訪問CSS類。不過,有很多外部類庫提供了可以訪問CSS類名(類似于 getElementsByClassName) 的方法。

<2>.HTML 節(jié)點關(guān)系

關(guān)于HTML的另外比較有意思的一點就是標(biāo)記之間的關(guān)系,思考下面的問題:

    * 要怎樣才可以最容易地、通過最少的DOM遍歷來到達(dá)目標(biāo)節(jié)點?
    * 通過修改什么標(biāo)記,可以盡可能多地訪問到需要修改的子節(jié)點?
    * 一個給定的元素有什么屬性或信息可以用來到達(dá)另外一個元素?

遍歷DOM很耗資源而且速度很慢,這就是為什么要盡量使用瀏覽器中已經(jīng)在使用的技術(shù)來做這件事情。

3.把遍歷交給專家來做
(CSS,更快地遍歷DOM)

有關(guān)DOM的腳本和使用方法或?qū)傩裕╣etElementsByTagName, nextSibling, previousSibling, parentNode以及其它)來遍歷DOM似乎迷惑了很多人,這點很有意思。而有趣的是,我們其實早已經(jīng)通過另外一種技術(shù)—— CSS ——做了這些事情。

CSS 是這樣一種技術(shù),它使用CSS選擇器,通過遍歷DOM來訪問目標(biāo)元素并改變它們的視覺屬性。一段復(fù)雜的使用DOM的JavaScript可以用一個CSS選擇器取代:



Java代碼


  1. var n = document.getElementById('nav');   

  2. if(n){   

  3. var as = n.getElementsByTagName('a');   

  4. if(as.length > 0){   

  5. for(var i=0;as[i];i++){   

  6. as[i].style.color = ‘#369′;   

  7. as[i].style.textDecoration = ‘none’;   

  8. }   

  9. }   

  10. }   

  11.   

  12. /* 下面的代碼與上面功能一樣 */  

  13.   

  14. #nav a{   

  15. color:#369;   

  16. text-decoration:none;   

  17. }  


這是一個可以好好利用的很強大的技巧。你可以通過動態(tài)為DOM中高層的元素添加class 或者更改元素ID來實現(xiàn)這一點。如果你使用DOM為文檔的body添加了一個CSS類,那么設(shè)計師就很可以容易地定義文檔的靜態(tài)版本和動態(tài)版本。




Java代碼


  1. JavaScript:   

  2.   

  3. var dynamicClass = 'js';   

  4. var b = document.body;   

  5. b.className = b.className ? b.className + ' js' : 'js';   

  6.   

  7. CSS:   

  8.   

  9. /* 靜態(tài)版本 */  

  10.   

  11. #nav {   

  12. ....   

  13. }   

  14.   

  15. /* 動態(tài)版本 */  

  16.   

  17. body.js #nav {   

  18. ....   

  19. }  


4.理解瀏覽器和用戶
(在既有的使用模式上創(chuàng)建你所需要的東西)

不唐突的JavaScript 中很重要的一部分就是理解瀏覽器是如何工作的(尤其是瀏覽器是如何崩潰的)以及用戶期望的是什么。不考慮瀏覽器你也可以很容易地使用JavaScript 創(chuàng)建一個完全不同的界面。拖拽界面,折疊區(qū)域,滾動條和滑動塊都可以使用JavaScript創(chuàng)建,但是這個問題并不是個簡單的技術(shù)問題,你需要思考下面的問題:

    * 這個新界面可以獨立于輸入設(shè)備么?如果不能,那么可以依賴哪些東西?
    * 我創(chuàng)建的這個新界面是否遵循了瀏覽器或者其它富界面的準(zhǔn)則(你可以通過鼠標(biāo)在多級菜單中直接切換嗎?還是需要使用tab鍵?)
    * 我需要提供什么功能但是這個功能是依賴于JavaScript的?

最后一個問題其實不是問題,因為如果需要你就可以使用DOM來憑空創(chuàng)建HTML。關(guān)于這點的一個例子就是“打印”鏈接,由于瀏覽器沒有提供一個非 JavaScript的打印文檔功能,所以你需要使用DOM來創(chuàng)建這類鏈接。同樣地,一個實現(xiàn)了展開和收縮內(nèi)容模塊的、可以點擊的標(biāo)題欄也屬于這種情況。標(biāo)題欄不能被鍵盤激活,但是鏈接可以。所以為了創(chuàng)建一個可以點擊的標(biāo)題欄你需要使用JavaScript將鏈接加入進(jìn)去,然后所有使用鍵盤的用戶就可以收縮和展開內(nèi)容模塊了。

解決這類問題的極好的資源就是設(shè)計模式庫。至于要知道瀏覽器中的哪些東西是獨立于輸入設(shè)備的,那就要靠經(jīng)驗的積累了。首先你要理解的就是事件處理機(jī)制。

5.理解事件
(事件處理會引起改變)

事件處理是走向不唐突的JavaScript的第二步。重點不是讓所有的東西都變得可以拖拽、可以點擊或者為它們添加內(nèi)聯(lián)處理,而是理解事件處理是一個可以完全分離出來的東西。我們已經(jīng)將HTML,CSS和JavaScript分離開來,但是在事件處理的分離方面卻沒有走得很遠(yuǎn)。

事件處理器會監(jiān)聽發(fā)生在文檔中元素上的變化,如果有事件發(fā)生,處理器就會找到一個很奇妙的對象(一般會是一個名為e的參數(shù)),這個對象會告訴元素發(fā)生了什么以及可以用它做什么。

對于大多數(shù)事件處理來說,真正有趣的是它不止發(fā)生在你想要訪問的元素上,還會在DOM中較高層級的所有元素上發(fā)生(但是并不是所有的事件都是這樣,focus和blur事件是例外)。舉例來說,利用這個特性你可以為一個導(dǎo)航列表只添加一個事件處理器,并且使用事件處理器的方法來獲取真正觸發(fā)事件的元素。這種技術(shù)叫做事件委托,它有幾點好處:

    * 你只需要檢查一個元素是否存在,而不需要檢查每個元素
    * 你可以動態(tài)地添加或者刪除子節(jié)點而并不需要刪除相應(yīng)的事件處理器
    * 你可以在不同的元素上對相同的事件做出響應(yīng)

需要記住的另一件事是,在事件向父元素傳播的時候你可以停止它而且你可以覆寫掉HTML元素(比如鏈接)的缺省行為。不過,有時候這并不是個好主意,因為瀏覽器賦予HTML元素那些行為是有原因的。舉個例子,鏈接可能會指向頁面內(nèi)的某個目標(biāo),不去修改它們能確保用戶可以將頁面當(dāng)前的腳本狀態(tài)也加入書簽。

6.為他人著想
(命名空間,作用域和模式)

你的代碼幾乎從來不會是文檔中的唯一的腳本代碼。所以保證你的代碼里沒有其它腳本可以覆蓋的全局函數(shù)或者全局變量就顯得尤為重要。有一些可用的模式可以來避免這個問題,最基礎(chǔ)的一點就是要使用 var 關(guān)鍵字來初始化所有的變量。假設(shè)我們編寫了下面的腳本:




Java代碼


  1. var nav = document.getElementById('nav');   

  2. function init(){   

  3. // do stuff   

  4. }   

  5. function show(){   

  6. // do stuff   

  7. }   

  8. function reset(){   

  9. // do stuff   

  10. }  

上面的代碼中包含了一個叫做nav的全局變量和名字分別為 init,show 和 reset 的三個函數(shù)。這些函數(shù)都可以訪問到nav這個變量并且可以通過函數(shù)名互相訪問:




Java代碼


  1. var nav = document.getElementById('nav');   

  2. function init(){   

  3. show();   

  4. if(nav.className === 'show'){   

  5. reset();   

  6. }   

  7. // do stuff   

  8. }   

  9. function show(){   

  10. var c = nav.className;   

  11. // do stuff   

  12. }   

  13. function reset(){   

  14. // do stuff   

  15. }  


你可以將代碼封裝到一個對象中來避免上面的那種全局式編碼,這樣就可以將函數(shù)變成對象中的方法,將全局變量變成對象中的屬性。 你需要使用“名字+冒號”的方式來定義方法和屬性,并且需要在每個屬性或方法后面加上逗號作為分割符。




Java代碼


  1. var myScript = {   

  2. nav:document.getElementById('nav'),   

  3. init:function(){   

  4. // do stuff   

  5. },   

  6. show:function(){   

  7. // do stuff   

  8. },   

  9. reset:function(){   

  10. // do stuff   

  11. }   

  12. }  


所有的方法和屬性都可以通過使用“類名+點操作符”的方式從外部和內(nèi)部訪問到。



Java代碼


  1. var myScript = {   

  2. nav:document.getElementById('nav'),   

  3. init:function(){   

  4. myScript.show();   

  5. if(myScript.nav.className === 'show'){   

  6. myScript.reset();   

  7. }   

  8. // do stuff   

  9. },   

  10. show:function(){   

  11. var c = myScript.nav.className;   

  12. // do stuff   

  13. },   

  14. reset:function(){   

  15. // do stuff   

  16. }   

  17. }  


這種模式的缺點就是,你每次從一個方法中訪問其它方法或?qū)傩远急仨氃谇懊婕由蠈ο蟮拿郑覍ο笾械乃袞|西都是可以從外部訪問的。如果你只是想要部分代碼可以被文檔中的其他腳本訪問,可以考慮下面的模塊(module)模式:



Java代碼


  1. var myScript = function(){   

  2. //這些都是私有方法和屬性   

  3. var nav = document.getElementById('nav');   

  4. function init(){   

  5. // do stuff   

  6. }   

  7. function show(){   

  8. // do stuff   

  9. }   

  10. function reset(){   

  11. // do stuff   

  12. }   

  13. //公有的方法和屬性被使用對象語法包裝在return 語句里面   

  14. return {   

  15. public:function(){   

  16.   

  17. },   

  18. foo:'bar'  

  19. }   

  20. }();  


你可以使用和前面的代碼同樣的方式訪問返回的公有的屬性和方法,在本示例中可以這么訪問:myScript.public() 和 myScript.foo 。但是這里還有一點讓人覺得不舒服:當(dāng)你想要從外部或者從內(nèi)部的一個私有方法中訪問公有方法的時候,還是要寫一個冗長的名字(對象的名字可以非常長)。為了避免這一點,你需要將它們定義為私有的并且在return語句中只返回一個別名:



Java代碼


  1. var myScript = function(){   

  2. // 這些都是私有方法和屬性   

  3. var nav = document.getElementById('nav');   

  4. function init(){   

  5. // do stuff   

  6. }   

  7. function show(){   

  8. // do stuff   

  9. // do stuff   

  10. }   

  11. function reset(){   

  12. // do stuff   

  13. }   

  14. var foo = 'bar';   

  15. function public(){   

  16.   

  17. }  


//只返回指向那些你想要訪問的私有方法和屬性的指針



Java代碼


  1. return {   

  2. public:public,   

  3. foo:foo   

  4. }   

  5. }();  


這就保證了代碼風(fēng)格一致性,并且你可以使用短一點的別名來訪問其中的方法或?qū)傩浴?

如果你不想對外部暴露任何的方法或?qū)傩裕憧梢詫⑺械拇a封裝到一個匿名方法中,并在它的定義結(jié)束后立刻執(zhí)行它:




Java代碼


  1. (function(){   

  2. // these are all private methods and properties   

  3. var nav = document.getElementById('nav');   

  4. function init(){   

  5. // do stuff   

  6. show(); // 這里不需要類名前綴   

  7. }   

  8. function show(){   

  9. // do stuff   

  10. }   

  11. function reset(){   

  12. // do stuff   

  13. }   

  14. })();  


對于那些只執(zhí)行一次并且對其它函數(shù)沒有依賴的代碼模塊來說,這種模式非常好。

通過遵循上面的那些規(guī)則,你的代碼更好地為用戶工作,也可以使你的代碼在機(jī)器上更好地運行并與其他開發(fā)者的代碼和睦相處。不過,還有一個群體需要考慮到。

7.為接手的開發(fā)者考慮
(使維護(hù)更加容易)

使你的腳本真正地unobtrusive的最后一步是在編寫完代碼之后仔細(xì)檢查一遍,并且要照顧到一旦腳本上線之后要接手你的代碼的開發(fā)者。考慮下面的問題:

    * 所有的變量和函數(shù)名字是否合理并且易于理解?
    * 代碼是否經(jīng)過了合理的組織?從頭到尾都很流暢嗎?
    * 所有的依賴都顯而易見嗎?
    * 在那些可能引起混淆的地方都添加了注釋嗎?

最重要的一點是:要認(rèn)識到文檔中的HTML和CSS代碼相對于JavaScript來說更有可能被改變(因為它們負(fù)責(zé)視覺效果)。所以不要在腳本代碼中包含任何可以讓終端用戶看到的class和ID,而是要將它們分離出來放到一個保存配置信息的對象中。




Java代碼


  1. myscript = function(){   

  2. var config = {   

  3. navigationID:'nav',   

  4. visibleClass:'show'  

  5. };   

  6. var nav = document.getElementById(config.navigationID);   

  7. function init(){   

  8. show();   

  9. if(nav.className === config.visibleClass){   

  10. reset();   

  11. };   

  12. // do stuff   

  13. };   

  14. function show(){   

  15. var c = nav.className;   

  16. // do stuff   

  17. };   

  18. function reset(){   

  19. // do stuff   

  20. };   

  21. }();  


這樣維護(hù)者就知道去哪里修改這些屬性,而不需要改動其他代碼。

 

該文章在 2011/3/25 11:33:42 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運作、調(diào)度、堆場、車隊、財務(wù)費用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務(wù)都免費,不限功能、不限時間、不限用戶的免費OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved