無入侵指令碼編程(unobtrusive scripting)
一個無入侵的指令碼應該包括如下的所有特徵:
1、它應該是可用的。即給網站帶來了明確的可用性好處。
2、它應該是可訪問的。即如果javascript失效了,網頁應該依然是可閱讀和可理解的,及時不可避免的損失了一些可用性。
3、它應該容易實現。典型的情況:web開發人員只需要在頁面中引入指令碼本身和一個javascript鉤子(hook),然後指令碼就可以運行了。
4、它應該是分離的。它只存在於自己的.js檔案中,而不是散落在HTML的各個角落。
三個層
一個web頁面由如下三個層組成:
1、HTML結構層 2、CSS表現層 3、JavaScript行為層
分離關注點
把用戶端代碼分為三個層還引入了另一個話題,幾分利關注點。一般來說,最好能把三個層分開來管理。最基本的要求是確保要做到如下幾點:
1、HTML是結構化的,不要太複雜,而且在沒有CSS和JavaScript的情況下要有意義。
2、CSS表現層和JavaScript行為層分別放置於.css檔案和.js檔案中。
分離關注點方便維護,此外分離使你可以改變整個CSS表現層,給你的網站一個全新的設計,而且既不用重寫HTML結構,也不用重寫JavaScript行為層。
三個分離-- 表現與結構分離
分離表現層和結構層的基本思想就是確保由HTML來定義結構(且之定義結構),而所有表現都定義在另一個單獨的CSS檔案中。
css修改:javascript允許修改css,通常即時修改css的最好辦法是改變一個元素的className。
更改結構還是表現:有兩種方法來隱藏表單域
1、用css是它們不可見(display:none)--表現層
2、從文檔結構中將它們徹底移除。--結構層
但是要注意,當提交表單的時候,瀏覽器會給所有的表單域建立名/值對,然後再把它們發送給伺服器。如果我們把一些不需要的表單通過css隱藏,則這些表單域仍然是表單的一部分,不過是隱藏了而已,因此,它們也會被發送到伺服器,即使它們是沒用的。
相對地,如果從文檔結構中把這些表單域完全的移除,它們就不會被發送到伺服器,即使它們是沒用的。
推薦:最好把表單域直接移除,而不是隱藏它們。
三個分離-- 行為與結構分離
行為與結構分離比較容易理解:不把任何javascript代碼寫到你的HTML頁面裡。這需要兩個步驟:
1、把所有的javascript函數都放到一個獨立的.js檔案中,然後把它鏈入到所有需要它的HTML頁面。
2、從HTML中移除所有的事件處理常式,把它們放到同一個.js檔案裡。
<a href="somepage.html" id="nifty">DO it!</a>//單獨的js檔案中document.getElementById('nifty').onclick = doAllKindOfNiftyThings;
三個分離-- 行為與表現分離
事實上,存在著CSS和javascript重合的灰色地帶,不能清除地把某個效果歸為表現還是行為。
所以,如果需要建立“相似但不完全相同”的效果時,比如mouseover,javascript是最有效方法,當你必須在css和javascript之間做出選擇時,請記住這一點。
可訪問性規則
1、條理分明的HTML (硬式編碼連結必須有href)
2、產生對指令碼使用者有意義的內容
a.觸發進階指令碼的連結(如果給連結加上href不可行,那麼久用javascript來產生連結,如下代碼:)
var link = document.createElement("a"); link.href = "#"; link.onclick = starUpAjaxStuff; var linkText = document.createTextNode('Commmence coolness'); link.appendChild(linkText); document.body.appendChild(link); function starUpAjaxStuff(){ alert("ok"); }
b.用javascript隱藏內容(隱藏內容是危險的,如果沒有javascript,內容就永遠不會變的可見,而這個頁面就不具備可訪問性)
c.重新導向使用者
有時候,解決可訪問性的問題的最佳辦法就是為你的網站同時建立一個有指令碼版本和一個無指令碼版本。我不喜歡這個解決方案,盡量避免它,但是,實踐證
明它還是有價值的。
如果你使用這種方法,就應該遵循如下兩條規則:
首先,你網站的入口頁面應該是一個無指令碼頁面,這樣,所有的瀏覽器,即使是那些只能支援HTML的瀏覽器都可以得到一個可以使用的頁面。這樣,所有
的瀏覽器,即使是那些只能支援HTML的瀏覽器,都可以得到一個可以使用的頁面。
第二,當瀏覽器達到這個無指令碼頁面時,啟動一段指令碼來檢測它是否可以支援你的進階指令碼,如果可以,就用replace()方法把它們轉向到有指令碼頁面。
這裡需要注意的是,location.href會在瀏覽器的記錄中建立一條新紀錄,如果使用者到達無指令碼頁面,她就被轉向到有指令碼頁面。然而,一旦她
點擊後退按鈕,就會被回送到無指令碼頁面,而上述的指令碼又會立刻啟動,並且又把它回送到有指令碼頁面,後退按鈕的功能事實上被破壞了。
所以,使用location.replace()方法,它會載入一個新頁面,但它會覆蓋舊頁面在瀏覽器中的記錄,這個時候後退按鈕可以一直正常工作。