2011-11-06 57 views
2

JavaScript在大多數Web解決方案中扮演着越來越重要的角色,但我發現將JS代碼從視圖細節中分離出來要比在服務器端代碼中分離要困難得多。尋求關於如何從視圖中分離JS代碼的建議

人們使用什麼技術來分離JS代碼,以減少維護負擔並使其儘可能適應小的視圖更改?

爲了提供一個具體的例子,我有一個看起來有點像下面這樣的觀點:

<div id="signin" class="auth"> 
    <h2>Sign in</h2> 
    <div id="resultbox" class="box" style="display: none;"></div> 

    <div class="form"> 
     <p>Required fields are marked <span class="yellow">*</span></p> 
     <form action="@Url.Action(MVC.Account.Authenticate())" method="post" id="authform"> 
      <label for="Identification">Alias or email <span class="yellow">*</span></label></p> 
      @Html.TextBoxFor(m => m.Identification, new { size="22", tabindex="1" }) 

      <label for="Password">Password <span class="yellow">*</span></label></p> 
      @Html.PasswordFor(m => m.Password, new { size="22", tabindex="2" }) 

      <a href="#" class="but_styled" id="btn_signin" tabindex="3">Sign in</a> 
     </form> 
    </div> 
</div> 

JS部分被分成兩個文件 - 第一個是我的「商業邏輯」級和第二主要用於配線:

(function (pp, $, undefined) { 
    pp.account = {}; 

    function hideResultBox() { 
     var box = $('#resultbox'); 
     box.hide(); 
     box.removeClass('info_box').removeClass('error_box'); 
    } 
    function showResultBox(result) { 
     var box = $('#resultbox'); 
     if (result.Success === true) { 
      $('#resultbox_content').html(result.Message); 
      box.addClass('info_box').show(); 
     } else { 
      $('#resultbox_content').html(result.Message); 
      box.addClass('error_box').show(); 
      var messages = ''; 
      for (var error in result.Errors) { 
       messages += '<li>' + result.Errors[error] + '</li>'; 
      } 
      if (messages !== '') 
       $('#resultbox_content').append('<br /><ul>' + messages + '</ul>'); 
     } 
    } 

    pp.account.authenticate = function (data) { 
     hideResultBox(); 
     $.post('/account/authenticate', data, function (result) { 
      showResultBox(result); 
      if (result.Success === true) { 
       setTimeout(function() { window.location = result.Url; }, 1000); 
      } 
     }); 
    }; 
})(window.pressplay = window.pressplay || {}, jQuery); 

和配線部分:

$(document).ready(function() { 
    $('#signin a').live('click', function() { 
     var form = $(this).closest('form').serialize(); 
     pressplay.account.authenticate(form); 
     return false; 
    }); 
}); 

的問題上面的代碼是如何緊密地與視圖的外觀(必須呈現的元素ID,結構等)緊密聯繫在一起,但我對如何改進它沒有好的想法。

在我看來,如果我繼續沿着這條道路走下去,那麼JS文件最終會變成一個正確封裝的邏輯,並結合各種視圖特定的東西。

這是我希望做的最好的或者是否有我可以應用的技術來避免這些混亂?

我自己關於如何改進這個問題的想法圍繞着構建某種服務器端生成的「元素選擇器」JS類,這樣我就可以編寫JS,而不必使用類和引用元素ID的很多字符串引用。但我不確定人們會怎麼做,或者最終是否會變得更糟。

回答

3

的幾點思考:

  • 請在元素「ID」值不是基本功能,除了視圖的功能,確實涉及到的「自然」的獨特元素。儘可能使用類。
  • 使用「data-」屬性將功能配置信息從HTML傳遞到JavaScript。 (但是不要把代碼放在你的「數據」屬性中;在我看來這是一個非常糟糕的主意,對不起,Knockout的粉絲)
  • 使用事件發佈/訂閱系統進行通信在功能「捆綁」之間保持相互依存關係的控制。
  • 使用<body>類來表徵不同類型的頁面,以提高「佈線」的效率。這樣,功能代碼可以很快地告訴您是否需要對給定頁面進行考慮。

編輯 —澄清最後一個:讓我們說你有一些功能,都與<form>頁面,例如日期選擇器,或自動完成輸入,或其他類似的東西。有時候,有些功能只對某些種類有意義。在這樣的情況下,使用體類可以簡單計算出一個功能是否應該刻意去看看周圍的DOM元素的影響:

if ($('body').is('.password-form')) { 
    // perform specific initializations 
} 

我目前參與的Web應用程序是不是太很大,但也不是微不足道的。我發現我可以爲整個站點保留一大堆JavaScript,並且在每個頁面上都包含相同的內容,而且我沒有任何性能問題(目前)(IE7很慢,但這種技術不是導致那)。

+0

你能否提供最後兩個項目符號的示例(或者鏈接到某個項目)?我不完全確定如何將這些建議轉化爲我可以應用的有形內容。 –

+0

第三個項目符號是關於名爲'Publisher/Subscriber'的設計模式:http://en.wikipedia.org/wiki/Publish/subscribe –

+0

+1,也是因爲您提到了數據屬性的使用!記得很清楚。 =) –

1

JavaScript仍然是你的觀點的一部分,所以我不相信是一個設計太糟糕了你的JavaScript與你的觀點交織在一起。

爲了讓生活更輕鬆,我認爲你真的需要盡你所能去尋找常見的javascript編碼情況,並將它們重新排列在視圖之外,並將它們重構成一個共同的庫,使用和重複使用。例如,如果你改寫了你的hideResultBox看起來像這樣:

function hideElement(var jqElementSelector, var cssClass1, var cssClass2 var cssClass3) { 
    var element = $(jqElementSelector); 
    element.hide(); 
    element.removeClass(cssClass1).removeClass(cssClass2).removeClass(cssClass3); 
} 

然後你可以取代你的電話在這個觀點是這樣的:

CommonLib.hideElement('#resultbox', 'info_box', 'error_box'); 

這樣至少你不必儘可能多的JavaScript維護。這也會讓從服務器生成javascript調用點變得更容易,因爲您沒有傳入邏輯,只需要名稱&或ids,而不必擔心在您的javascript邏輯中丟失任何類型的javascript intellisense功能。

+0

這是有道理的,但似乎只解決了一小部分的問題。我仍然有一個相當緊密的耦合,但正如你所說,也許它是視圖的一部分,我應該學會忍受它;) –

+0

如果宗教地使用,您的視圖的JavaScript將有很少或沒有邏輯,這是我想象中最好的一個希望。 – Daryl

+0

是的,但我仍然需要調用這些方法並傳入適當的值。這些調用可能位於其他代碼中。最終,我的「public api」方法將有100個參數來包含給定調用圖中所需的所有選擇器,我不認爲這是一個理想的解決方案。 –

1

相反的ID,我會覺得更「功能性的方式」 ... 即先想想什麼是JavaScript代碼的功能, 則使代碼的方式,它可以被你的觀點使用。

您是否看到區別?

你現在的做法是:先查看,然後javascript代碼...我建議的是:先javascript,然後查看元素。這樣你就可以確定你正在編寫一個可重用的JavaScript代碼庫。

而不是使用ID,使用類。使代碼像通用目錄庫一樣,你可以重用。不需要固定的結構,例如「.myClass div a」...該div可以殺死可重用性...將其替換爲某個內部類:「.myClass .innerClass a」,這樣您就可以將類應用於您的視圖,而不是讓視圖支配代碼。

儘量減少JavaScript代碼直接放入您的視圖。只需使用方法調用您自己的庫,使用簡單和描述性的方法名稱。嘗試把你的JavaScript放在一起。儘量不要使用聲明式JavaScript ...因爲我看到你已經這樣做了。這是要走的路! =)

不要擔心可維護性問題,因爲解耦是增加可維護性的一種經過證明的方式。

+0

好的建議,特別是繞過固定結構的提示。我必須首先嚐試JS,但不知何故,在我知道我需要它之前,感覺就像編寫邏輯一樣。我會給它一個嘗試:) –

+0

*然後不要在知道你需要什麼之前編寫邏輯!*但是,也不要讓你發現你需要什麼,只有當你把手放在你的視圖*上時。你的第一視圖應該只是一個模型,然後你創建代碼,最後回到你的模型視圖,並將其調整爲代碼。 =) –

+0

我喜歡那樣!儘管我在當前的項目中使用它很難,因爲我購買了大量不同頁面和樣式的網頁模板。我正在修改它們,但是我或多或少地開始使用接近完成的靜態視圖。下一次,我會聘請某人在事後對其進行風格改造,而不是=) –

相關問題