mozilla

修改 233812 of Writing forward-compatible websites

  • 版本網址代稱: Web_development/Writing_forward-compatible_websites
  • 版本標題: Writing forward-compatible websites
  • 版本 ID: 233812
  • 建立日期:
  • 建立者: Littlebtc
  • 是目前線上的版本?
  • 回應 code cleanups; 18 words added, 44 words removed

版本內容

這個頁面將解釋如何撰寫在新的瀏覽器版本發布時不會遭受毀損的網頁。

這對內部網路和其他非公共網站尤其重要,如果我們不能看到你的原始碼,我們將無法看到它是否已遭受毀損。底下所提到的原則可能無法全數做到,但盡可能遵守這些原則,對於你的網站在未來發展維護上有所幫助。

JavaScript

以「window.」前綴修飾所有存取於 onfoo 屬性的全域變數

當一個事件處理器內容屬性(例如:onclick, onmouseover 等等)被使用在 HTML 的元素上時,所有對於屬性內名稱的查找首先發生在元素本身,若元素為表單控制項,再來尋找元素的表單,接著是 document,最後是 window(你定義全域變數的地方)。例如,如果你有這樣的原始碼:

<div onclick="alert(ownerDocument)">Click me</div>

在點選文字時,div 中的 ownerDocument 會被提示,即使是在全域範圍內宣告 var ownerDocument 這種情況依然會發生。

這意味著,無論你何時在事件處理器內容屬性存取了一個全域變數,包括呼叫任何全域函數,當規格中新增了和您變數或函式同名的 DOM 屬性到元素或文件之中,在瀏覽器實作之後,就會產生名稱衝突。這時你的函式將突然被停止呼叫。這種情況在 HTML5 的發展之下,多次在不同網站中發生。

為了避免這種情況,以 window 來限定全域變數的存取,例如:

<script>
  function localName() {
    alert('Function localName has been called');
  }
</script>
<div onclick="window.localName()">Clicking me should show an alert<div>

不要直接附加非您能控制的腳本

"use strict;" 指令在 ECMAScript 裡,使用於檔案層級時適用於檔案的所有程式碼。因此,若將取決非嚴格模式行為的腳本直接附加到要求<嚴格模式的腳本會導致不正常的行為。>

要求 JavaScript 函式庫的作者遵守這些規則

向您喜歡的函式庫開發者們建議他們遵循這些規範,否則您無法確保未來這些函式庫能否依舊正常運作。可惜的是函式庫往往違反這些準則。

偵測

偵測特定功能支援

如果您打算使用某些功能,盡可能使用物件偵測來偵測功能是否支援。簡單來說,不要假設只要 "filter" in body.style 測試結果為 true 的瀏覽器必定是 Microsoft Internet Explorer,進而我們一定會有 window.event 物件提供事件處理器。不要假設一個擁有特定 DOM 功能的瀏覽器一定也有另外一個 DOM 功能(特別是非標準功能);或著反過來假設一定不會支持某些功能(例如,假設在腳本元素中支援 onload 的瀏覽器一定不會支援 onreadystatechange)。隨著瀏覽器們整合他們的行為,它們會同時新增和刪除許多功能並修正錯誤。過去即是如此,未來也將會如此。

所以,在偵測特定功能時,不要接著假定「只要某個功能支援與否,另外一樣功能就一定支援與否」。

別做 UA 偵測

這就是假設一項功能存在(User Agent 中包含特定的字元)時,必定有哪些東西可用或不可用的常見實例。

如果您不得不做 UA 偵測,僅針對過去的瀏覽器版本

如果您還是得訴諸 UA(User Agent)偵測,請只針對特定瀏覽器的過去版本進行偵測。首先,對於未知的、所測試瀏覽器的目前與未來版本執行預設的程式內容。接著如果無法透過偵測,找出過去瀏覽器版本中預設程式內容中無法使用的功能,就可以透過偵測特定瀏覽器的過去版本來追加對應的修正。

在這個提案中,「目前的版本」意指您所能測試到的最新版本。如果您的預設程式內容在 Firefox Aurora 中可以正常運作,而在 Beta 和最新釋出版中存在問題而無法運作,此時您可以將您所測試中的 Firefox Aurora 版本標為「目前的版本」,將 Beta 以前的版本都視為「過去的版本」,即使它們還沒有被正式釋出給大眾。

不要為了不同的瀏覽器設計多餘的對應程式

當您所用的一部分程式內容可能在所有瀏覽器都能運作時,別隨便透過物件或 UA 偵測來決定執行不同的程式碼。瀏覽器很有可能改變它們的行為並互相整合,若您任意切出不同的替代程式,您的網站將有可能會損壞。

測試

測試所有主流引擎

至少在 Firefox、Chrome 或 Safari(因為兩者都基於相同的 WebKit 引擎)、Opera 及 Internet Explorer 測試您的程式碼。若遵循以上原則,你有一個單一的程式碼內容在目前所有的和未知的瀏覽器都測試過,在所有主要引擎都能運作下,極有可能表示您的程式碼將不會在未來被破壞。

有時不同瀏覽器對特定功能的實作不盡相同。如果你有一個單一的程式碼內容,在所有常用的引擎中都沒問題,這可能表示,你使用了各瀏覽器間已經整合的行為,或著使用了尚未整合,而程式碼無關引擎的行為標準所堅持的部份。

特定瀏覽器支援的功能和前綴

別針對目前或未來的瀏覽器版本做臨時方案

這也是一個共同的假設目前的錯誤之間的相關性之間意味著未來的錯誤相關性的實例。針對舊版本的瀏覽器的當前版本不再有錯誤,你靠你的黑客是確定的,一旦瀏覽器有修改X錯誤,你可以知道,對於某些有錯誤X的所有版本,也有錯誤Ÿ,使用存在缺陷X目標的解決方法去針對錯誤Y。

對於這樣的忠告,“當前”是指一個以上的UA嗅探意見的情況下,你已經測試瀏覽器的最新版本。

避免依賴新潮的非標準功能

即使前綴功能,使用它可能是危險的:作為規範的發展同樣可以改變瀏覽器的前綴實施跟踪規範。一旦特點被標準化,前綴的版本是有可能被刪除。

前綴,瀏覽器開發者提供非標準功能試驗,並提供反饋,是注定不會被開發。如果您選擇使用它們,需要經常更新您的網站以趕上變化。

當使用未普遍實作(即使是標準)的新潮功能時,記得測試備援方案

要確保測試在瀏覽器中沒有實現的功能當你使用,特別是如果你不每天使用這種瀏覽器當在網站上的工作時。

除非針對過去有問題的版本,不要使用廠商前綴(Vender-prefix)功能

賣方前綴的功能,可以在將來的版本中改變。然而,一旦瀏覽器出貨量已沒有前綴的功能,您可以使用前綴版本針對舊版本,確保總是使用不帶前綴的功能版本可用時。一個很好的例子,對越南盾的CSS前綴,已售出的牌子,它漂亮的財產沒有前綴的實施,使用行為的價值“有時”,從不同的前綴版本的瀏覽器供應商:

<style>
  .pretty-element {
    -vnd-make-it-pretty: sometimes;
    make-it-pretty: sometimes;
  }
</style>

上述規則的聲明的順序是很重要的:沒有前綴的人需要排在最後。

在沒有瀏覽器支援前,不要使用不含前綴的 CSS 屬性或 API

直到有體面的東西沒有前綴的版本廣泛支持,其行為仍然可以以意想不到的方式改變。最特別的是,的版本,不要使用不帶前綴如果沒有瀏覽器支持。你不能假設,最終版本的語法,將是任何的前綴版本的語法相同。

程式碼維護

別忘了 >

透過驗證器可以確保這個問題不會發生,但即使你的網站沒有完全驗證,你仍應確保你所有的 > 字元都有出現。少了它可能會讓接下來的 Tag 名稱被當成上一個 Tag 所屬的屬性,而造成意想不到的結果。可能一小段沒問題,但接下來因為某段文字代表一個屬性而完全被破壞。舉例來說,以下是一段在不支援 HTML5 瀏覽器下可正常運作,但卻讓支援 HTML5 的瀏覽器無法正常運作的網頁程式碼:

<form action="http://www.example.com">
  <input type="submit" value="傳送此表單"
</form>

因為在 input Tag 的最後忘了加上 >

別把失敗的實驗品留在您的網頁程式碼裡

如果您想嘗試一個 CSS 屬性或其他的酷東西,但沒有效果,請記得拿掉。不然您無法預知這東西未來會做什麼壞事。

版本來源

<p>這個頁面將解釋如何撰寫在新的瀏覽器版本發布時不會遭受毀損的網頁。</p>
<p>這對內部網路和其他非公共網站尤其重要,如果我們不能看到你的原始碼,我們將無法看到它是否已遭受毀損。底下所提到的原則可能無法全數做到,但盡可能遵守這些原則,對於你的網站在未來發展維護上有所幫助。</p> <h2>JavaScript</h2>
<h3>以「<code>window.</code>」前綴修飾所有存取於 <code>onfoo</code> 屬性的全域變數</h3>
<p>當一個事件處理器內容屬性(例如:<code>onclick</code>, <code>onmouseover</code> 等等)被使用在 HTML 的元素上時,所有對於屬性內名稱的查找首先發生在元素本身,若元素為表單控制項,再來尋找元素的表單,接著是 document,最後是 window(你定義全域變數的地方)。例如,如果你有這樣的原始碼:</p> <pre>&lt;div onclick="alert(ownerDocument)"&gt;Click me&lt;/div&gt;</pre>
<p>在點選文字時,div 中的 ownerDocument 會被提示,即使是在全域範圍內宣告 var ownerDocument 這種情況依然會發生。</p>
<p>這意味著,無論你何時在事件處理器內容屬性存取了一個全域變數,包括呼叫任何全域函數,當規格中新增了和您變數或函式同名的 DOM 屬性到元素或文件之中,在瀏覽器實作之後,就會產生名稱衝突。這時你的函式將突然被停止呼叫。這種情況在 HTML5 的發展之下,多次在不同網站中發生。</p>
<p>為了避免這種情況,以 window 來限定全域變數的存取,例如:</p>
<pre>&lt;script&gt;
  function localName() {
    alert('Function localName has been called');
  }
&lt;/script&gt;
&lt;div onclick="<strong>window.</strong>localName()"&gt;Clicking me should show an alert&lt;div&gt;
</pre>
<h3>不要直接附加非您能控制的腳本</h3>
<p><code>"use strict;"</code> 指令在 ECMAScript 裡,使用於檔案層級時適用於檔案的所有程式碼。因此,若將取決非嚴格模式行為的腳本直接附加到要求&lt;嚴格模式的腳本會導致不正常的行為。&gt;</p> <h3>要求 JavaScript 函式庫的作者遵守這些規則</h3>
<p>向您喜歡的函式庫開發者們建議他們遵循這些規範,否則您無法確保未來這些函式庫能否依舊正常運作。可惜的是函式庫往往違反這些準則。</p> <h2>偵測</h2>
<h3>偵測特定功能支援</h3>
<p>如果您打算使用某些功能,盡可能使用物件偵測來偵測功能是否支援。簡單來說,不要假設只要 <code>"filter" in body.style</code> 測試結果為 true 的瀏覽器必定是 Microsoft Internet Explorer,進而我們一定會有 <code>window.event</code> 物件提供事件處理器。不要假設一個擁有特定 DOM 功能的瀏覽器一定也有另外一個 DOM 功能(特別是非標準功能);或著反過來假設一定不會支持某些功能(例如,假設在腳本元素中支援 <code>onload</code> 的瀏覽器一定不會支援 <code>onreadystatechange</code>)。隨著瀏覽器們整合他們的行為,它們會同時新增和刪除許多功能並修正錯誤。過去即是如此,未來也將會如此。</p>
<p>所以,在偵測特定功能時,不要接著假定「只要某個功能支援與否,另外一樣功能就一定支援與否」。</p> <h3>別做 UA 偵測</h3>
<p>這就是假設一項功能存在(User Agent 中包含特定的字元)時,必定有哪些東西可用或不可用的常見實例。</p> <h4>如果您不得不做 UA 偵測,僅針對過去的瀏覽器版本</h4>
<p>如果您還是得訴諸 UA(User Agent)偵測,請只針對特定瀏覽器的過去版本進行偵測。首先,對於未知的、所測試瀏覽器的目前與未來版本執行預設的程式內容。接著如果無法透過偵測,找出過去瀏覽器版本中預設程式內容中無法使用的功能,就可以透過偵測特定瀏覽器的過去版本來追加對應的修正。</p>
<p>在這個提案中,「目前的版本」意指您所能測試到的最新版本。如果您的預設程式內容在 Firefox Aurora 中可以正常運作,而在 Beta 和最新釋出版中存在問題而無法運作,此時您可以將您所測試中的 Firefox Aurora 版本標為「目前的版本」,將 Beta 以前的版本都視為「過去的版本」,即使它們還沒有被正式釋出給大眾。</p>
<h3>不要為了不同的瀏覽器設計多餘的對應程式</h3>
<p>當您所用的一部分程式內容可能在所有瀏覽器都能運作時,別隨便透過物件或 UA 偵測來決定執行不同的程式碼。瀏覽器很有可能改變它們的行為並互相整合,若您任意切出不同的替代程式,您的網站將有可能會損壞。 </p><h2>測試</h2>
<h3>測試所有主流引擎</h3>
<p>至少在 Firefox、Chrome 或 Safari(因為兩者都基於相同的 WebKit 引擎)、Opera 及 Internet Explorer 測試您的程式碼。若遵循以上原則,你有一個單一的程式碼內容在目前所有的和未知的瀏覽器都測試過,在所有主要引擎都能運作下,極有可能表示您的程式碼將不會在未來被破壞。</p>
<p>有時不同瀏覽器對特定功能的實作不盡相同。如果你有一個單一的程式碼內容,在所有常用的引擎中都沒問題,這可能表示,你使用了各瀏覽器間已經整合的行為,或著使用了尚未整合,而程式碼無關引擎的行為標準所堅持的部份。</p> <h2>特定瀏覽器支援的功能和前綴</h2> <div id="section_13"> <h3 class="editable">別針對目前或未來的瀏覽器版本做臨時方案</h3> <p>這也是一個共同的假設目前的錯誤之間的相關性之間意味著未來的錯誤相關性的實例。針對舊版本的瀏覽器的當前版本不再有錯誤,你靠你的黑客是確定的,一旦瀏覽器有修改X錯誤,你可以知道,對於某些有錯誤X的所有版本,也有錯誤Ÿ,使用存在缺陷X目標的解決方法去針對錯誤Y。</p> <p>對於這樣的忠告,“當前”是指一個以上的UA嗅探意見的情況下,你已經測試瀏覽器的最新版本。</p> </div> <div id="section_14"> <h3 class="editable">避免依賴新潮的非標準功能</h3> <p>即使前綴功能,使用它可能是危險的:作為規範的發展同樣可以改變瀏覽器的前綴實施跟踪規範。一旦特點被標準化,前綴的版本是有可能被刪除。</p> <p>前綴,瀏覽器開發者提供非標準功能試驗,並提供反饋,是注定不會被開發。如果您選擇使用它們,需要經常更新您的網站以趕上變化。</p> </div> <div id="section_15"> <h3 class="editable">當使用未普遍實作(即使是標準)的新潮功能時,記得測試備援方案</h3> </div> <p>要確保測試在瀏覽器中沒有實現的功能當你使用,特別是如果你不每天使用這種瀏覽器當在網站上的工作時。</p> <div id="section_16"> <h3 class="editable">除非針對過去有問題的版本,不要使用廠商前綴(Vender-prefix)功能</h3> <p>賣方前綴的功能,可以在將來的版本中改變。然而,一旦瀏覽器出貨量已沒有前綴的功能,您可以使用前綴版本針對舊版本,確保總是使用不帶前綴的功能版本可用時。一個很好的例子,對越南盾的CSS前綴,已售出的牌子,它漂亮的財產沒有前綴的實施,使用行為的價值“有時”,從不同的前綴版本的瀏覽器供應商:</p> <pre>&lt;style&gt;
  .pretty-element {
    -vnd-make-it-pretty: sometimes;
    make-it-pretty: sometimes;
  }
&lt;/style&gt;
</pre> <p>上述規則的聲明的順序是很重要的:沒有前綴的人需要排在最後。</p> </div> <div id="section_17"> <h3 class="editable">在沒有瀏覽器支援前,不要使用不含前綴的 CSS 屬性或 API</h3> </div> <p>直到有體面的東西沒有前綴的版本廣泛支持,其行為仍然可以以意想不到的方式改變。最特別的是,的版本,不要使用不帶前綴如果沒有瀏覽器支持。你不能假設,最終版本的語法,將是任何的前綴版本的語法相同。</p>
 <h2>程式碼維護</h2> <h3>別忘了 <code>&gt;</code></h3> <p>透過驗證器可以確保這個問題不會發生,但即使你的網站沒有完全驗證,你仍應確保你所有的 &gt; 字元都有出現。少了它可能會讓接下來的 Tag 名稱被當成上一個 Tag 所屬的屬性,而造成意想不到的結果。可能一小段沒問題,但接下來因為某段文字代表一個屬性而完全被破壞。舉例來說,以下是一段在不支援 HTML5 瀏覽器下可正常運作,但卻讓支援 HTML5 的瀏覽器無法正常運作的網頁程式碼:</p> <pre class="brush: html">&lt;form action="http://www.example.com"&gt;
  &lt;input type="submit" value="傳送此表單"
&lt;/form&gt;
</pre> <p>因為在 <code>input</code> Tag 的最後忘了加上 <code>&gt;</code>。</p> <h3>別把失敗的實驗品留在您的網頁程式碼裡</h3> <p>如果您想嘗試一個 CSS 屬性或其他的酷東西,但沒有效果,請記得拿掉。不然您無法預知這東西未來會做什麼壞事。</p>
還原至此版本