一個Web頁面的問題分析

一個Web頁面的問題分析

幾個月以前我接到一個新的開發任務,要在一箇舊的Web頁面上面增添一些新的功能。在開發的過程當中發現舊的代碼中有不少常見的不合適的寫法,結合這些問題,如何寫出更好的,更規範的,更可維護的代碼,就是這篇文章要闡述的內容。前端

首先我查看了該Web頁面的HTML代碼,發現了一些典型的問題:express

  • HTML頁面中包含了不少Javascript和CSS代碼
  • HTML頁面中引用了大量的外部Javascript文件和CSS文件

接下來就這些問題,咱們逐個討論一下:瀏覽器

HTML頁面中包含了不少Javascript和CSS代碼

一個正常的Web頁面一般有如下三部分組成,HTML,CSS,Javascript,其中HTML是數據,CSS負責樣式,而Javascript負責交互,三者的關係以下圖:服務器

     

在構建Web頁面的過程當中,要儘可能讓這三者保持鬆耦合的關係,不要牽一髮而動全身,一個層面小的改動須要改動另外兩個層面。首先要從文件級別上隔離這三部分,在HTML中經過引入文件的方式導入Javascript和CSS。併發

要作到三者的鬆耦合,開發中須要注意的地方又以下幾點:mvc

  • 在CSS代碼中不要包含Javascript
  • 在Javascript代碼中不要包含CSS
  • 在HTML代碼中不要包含Javascript
  • 在Javascript中不要包含HTML

CSS代碼中不要包含Javascript,指的是在CSS代碼中慎用可計算的樣式,如IE 8的 expression,CSS3的calc等等,從使用角度來說全是很強大,從代碼維護的角度來看,不推薦使用。出現了Bug的時候,須要同時Check Javascript和CSS代碼。app

Javascript代碼中不要包含CSS,咱們常常須要在Javascript中去動態改變某一個Dom元素的樣式,常常寫出以下代碼:asp.net

element.style.color = 'red';

這樣的代碼會致使當需求改變的時候,須要在Javascript代碼中全文檢索 red 關鍵字,深怕漏掉一點。推薦的作法以下:函數

//在CSS文件中定義樣式類型
.red-class{
   color: red;
}

//Javascript中改變樣式
element.className += " red-class";
// jQuery
$(element).addClass("red-class");

在Javascript中操縱Dom對象的Class來改變樣式,需求改變的時候,只須要調整CSS文件就能夠了。grunt

HTML代碼中不要包含Javascript:

<input type="button" value="click me" id="mybutton" onclick="do()"/>

推薦使用下面的代碼:

var btn = document.getElementById('mybutton');
btn.addEventListener("click", do);

Javascript代碼中不要包含HTML:

var div = document.getElementById("my-div");
div.innerHTML = "<h3>Error</h3><p>Invalid e-mail address.</p>";

在Javascript代碼中徹底隔絕HTML很難,這一點能夠根據實際狀況來權衡使用。Javascript 模版技術就是一種有效隔離HTML和Javascript代碼的手段,以下是jQuery Template的用法:

// HTML
<script id="bookTemplate" type="text/x-jQuery-tmpl">
        <div>
            <img src="BookPictures/${picture}" alt="" />
            <h2>${title}</h2>
            price: ${formatPrice(price)}
        </div>
 </script>

// Javascript
// Create an array of books
var books = [{ title: "ASP.NET 4 Unleashed", price: 37.79, picture: "AspNet4Unleashed.jpg" }];
// Render the books using the template
$("#bookTemplate").tmpl(books).appendTo("#bookContainer");
 
function formatPrice(price) {
      return "$" + price.toFixed(2);
}

 

HTML頁面中引用了大量的外部Javascript文件和CSS文件

HTML頁面中引用了大量的外部Javascript文件和CSS文件,咱們知道每個引用外部文件的<script>或者<style>都會引發一個HTTP請求,而一個HTTP請求的代價實際上是很高昂的,下圖是HTTP請求的整個過程:

首先要經過DNS Server把域名變爲IP,而後在瀏覽器與服務器之間創建TCP連接,創建TCP連接以後,瀏覽器向服務器發送HTTP請求,服務器處理完請求後,將結果返回給瀏覽器,最後關閉TCP連接。整個HTTP的請求的代價仍是很大的,更多關於HTTP和TCP的信息,請參考:http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocolhttp://en.wikipedia.org/wiki/Transmission_Control_Protocol

另外瀏覽器對於HTTP請求的併發數量是有限制的,每一個瀏覽器不等,基本在4個左右。

當HTML頁面中引用了大量的外部Javascript文件和CSS文件,咱們能夠考慮經過合併以及壓縮Javascript,CSS文件來達到減小HTTP請求數量,以及HTTP結果的目的。

Grunt是一個基於任務的JavaScript項目命令行構建工具,經過Grunt能夠將多個文件合併成一個文件,而且進行壓縮處理。Grunt沒有開發平臺的限制,只要是前端項目,均可以使用Grunt來配置任務。Grunt有着普遍的社區支持,有不少的現有的插件。

另外若是你是ASP.NET的項目的話,ASP.NET 4.5加入了Bundle,經過Bundle技術合併壓縮Javascript和CSS。關於Bundle技術能夠參考 http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

Javascript代碼全局變量

看完了HTML代碼以後,又過了一下頁面主要的Javascript代碼,發現的問題主要是Javascript代碼引入了太多的全局變量。JavaScript全局變量在很小的程序中可能會帶來方便,但隨着程序愈來愈大,它很快變得難以處理。由於一個全局變量能夠被程序的任何部分在任意時間改變,使得程序的行爲被極大地複雜化。在程序中使用全局變量下降了程序的可靠性。

定義Javascript的方式有三種:

//  在全部函數外部使用var定義變量
var foo = 10;

// 沒有使用var,直接聲明變量
foo = 10;

window.foo = 10;

其中第二種隱式的聲明瞭全局變量,尤爲須要注意。

咱們應該儘可能少的引入全局變量,jQuery也不過提供了兩個全局變量:$, jQuery。那麼有沒有可能在注入Javascript到HTML頁面以後,實現零個全局變量的引入那?

經過當即執行函數能夠達到這一點,參見下面的代碼:

(function(win) {
    "use strict";
    var doc = win.document;
    // declare other variables here
    // other code goes here
}(window));

若是你須要將該對象返回,可使用以下的方式:

var module1 = (function(){
    var _count = 0;
    var m1 = function(){
      //...
    };
    var m2 = function(){
      //...
    };
    return {
      m1 : m1,
      m2 : m2
    };
})();

這樣的話只會引入一個全局變量 module1,並且該對象具備很好的封裝性,其內部變量「_count」,在外部是沒法訪問的。

整個頁面其實也還有一些其餘小的問題,在這裏就不一一贅述了。

說了半天老代碼的問題,其實沒有對老代碼有任何偏見,由於不論它是否美醜,都在爲系統服務,都在產生價值。咱們只是在追求更好的代碼,更可讀,更易維護的代碼。

相關文章
相關標籤/搜索