2010-06-14 181 views
6

tl; dr:如何在JavaScript中以乾淨的方式實現MVC?JavaScript中的模型 - 視圖 - 控制器

我想在JavaScript中實現MVC。我已經無數次地用我的代碼進行了搜索和重組,但沒有找到合適的解決方案。 (該代碼只是不「感覺正確」。)

下面是我現在正在做的事情。這是非常複雜的,並且是一個痛苦的工作(但仍然比我之前的一堆代碼更好)。它具有醜陋的解決方法,這種方式可以擊敗MVC的目的。

不料,亂七八糟的,如果你真的勇敢:

// Create a "main model" 
var main = Model0(); 

function Model0() { 
    // Create an associated view and store its methods in "view" 
    var view = View0(); 

    // Create a submodel and pass it a function 
    // that will "subviewify" the submodel's view 
    var model1 = Model1(function (subview) { 
     view.subviewify(subview); 
    }); 

    // Return model methods that can be used by 
    // the controller (the onchange handlers) 
    return { 
     'updateModel1': function (newValue) { 
      model1.update(newValue); 
     } 
    }; 
} 

function Model1(makeSubView) { 
    var info = ''; 

    // Make an associated view and attach the view 
    // to the parent view using the passed function 
    var view = View1(); 
    makeSubView(view.__view); // Dirty dirty 

    // Return model methods that can be used by 
    // the parent model (and so the controller) 
    return { 
     'update': function (newValue) { 
      info = newValue; 

      // Notify the view of the new information 
      view.events.value(info); 
     } 
    }; 
} 

function View0() { 
    var thing = document.getElementById('theDiv'); 
    var input = document.getElementById('theInput'); 

    // This is the "controller", bear with me 
    input.onchange = function() { 
     // Ugly, uses a global to contact the model 
     main.updateModel1(this.value); 
    }; 

    return { 
     'events': {}, 

     // Adds a subview to this view. 
     'subviewify': function (subview) { 
      thing.appendChild(subview); 
     } 
    }; 
} 

// This is a subview. 
function View1() { 

    var element = document.createElement('div'); 
    return { 
     'events': { 
      // When the value changes this is 
      // called so the view can be updated 
      'value': function (newValue) { 
       element.innerHTML = newValue; 
      } 
     }, 

     // ..Expose the DOM representation of the subview 
     // so it can be attached to a parent view 
     '__view': element 
    }; 
} 

一個人如何在JavaScript中更清潔的方式實現MVC?我該如何改進這個系統?或者這是完全錯誤的路要走,我應該遵循另一種模式?

+0

(四年後)使用AngularJS。 – 2014-04-21 09:45:42

+1

如果您只是想了解MVC如何在Javascript中工作,那麼詢問如何實現它是非常合理的。太多的開發者現在都在使用框架,而沒有真正理解他們的工作方式。 – NobodyReally 2014-08-07 15:38:42

回答

0

說實話,MVC不太適合Javascript。它可以支持設計的基本原理,當然 - 您可以創建僞類作爲控制器或模型,支持基本繼承,並且可以讓它操縱或創建任意數量的DOM元素,但是您付出的代價是 - 在開銷,可訪問性和可用性方面。

在我看來,我認爲Javascript更多的是一種增強 - KISS的心態是存在的一個很好的理由。如果您對更好的方法來組織代碼感興趣,總是可以選擇將相關功能打包成模塊(原文如此),並根據需要抽取部分內容。例如,創建工廠以執行更復雜的AJAX請求管理,或者使用僞類來處理相似類型的數據。使用控制器的標準基本函數,模型等的另一個作爲這些對象的新實例的原型可以實現類似的功能......但是,這又有點違背Javascript的五穀。

不過,如果你被困在MVC的想法只是爲結構的緣故,可以考慮類似如下:

;(function(window, $) { 
    /** 
    * Event Object 
    * A quick description goes here. 
    **/ 
    var Events = window.Events = { 
     'bindTrackables': function() { 
      $('a.trackable').live('click', function() { 
       if(!_gaq) 
        _gaq = []; 
       _gaq.push(['_trackPageview', '/ajax/foobar']); 
      }); 
     }, 
     'bindSomeEvent': function() { 
      // etc 
     } 
    }; 

    /** 
    * Data Cache 
    * I'll need to remember stuff later, so I store it here 
    **/ 
    var Cache = window.Cache = { 
     'data': {}, 
     'store': function(key, value) { 
      Cache.data[key] = value; 
     }, 
     'fetch': function(key) { 
      return Cache.data[key]; 
     } 
    }; 

    /** 
    * Request Object 
    * Stores native AJAX requests for later use 
    **/ 
    var Request = window.Request = { 
     'current_requests': [], 
     'send': function(url, type, data, callback) { 
      Request.current_requests.push($.ajax({ 
       'url': url, 
       'type': type, 
       'data': data, 
       'callback': callback 
      })); 
     }, 
    } 

    // add some private logic here 
})(window, jQuery); 

這是非常基本的,但你的想法。模塊化代碼是關鍵......在JS中,這比強制應用程序(或語言)適合某種風格更重要。

+1

我完全同意你的觀點,但我的應用程序很複雜(這是一個Gmail應用程序 - 幾乎沒有那麼大,但關鍵還是在於)。即使組織與你的文章中的模型類似,代碼也是一團糟。我必須找到一些組織模式,所以我沒有發瘋。如果實施(好)很麻煩,我不需要堅持MVC,但是在那種情況下,我確實需要替代模式。 – 2010-06-14 19:23:04

6

對於JavaScript JavaScriptMVCpureMVC,至少有一些已建立和可用的MVC框架。可能還有更多。我已經使用基於瀏覽器和Air應用程序的JavaScriptMVC並繼續回到它 - 它有它的問題,但我發現它非常有用。
還有其他的解決方案,看看Sammy,這是我聽到的好消息。我沒有用過自己,但打算儘快嘗試。我對它的描述不夠充分,但對我來說,它似乎是一個在路線上工作的前端控制器,一個模板系統和ReSTful數據存儲。我不確定它是否是MVC,但具有相似的成分。我不得不不同意mway's answer。 MVC在JavaScript中可能有點不同,但其好處對於organising this mess非常重要。通常與面嚮對象語言相關的設計模式不會因爲js不是基於類而離開窗口。

我會說MVC比基於請求的(服務器端)應用程序更適合JavaScript應用程序。這些對象可以在一頁JavaScript應用程序中停留一段時間 - 分鐘(如果不是幾個小時) - 並且組織良好的組織交互的方式將使您的代碼更加健壯並易於處理。 There are books on the subject.

關於您發佈的代碼的其他幾點。

  • 視圖對象負責將事件偵聽器應用於DOM元素。這是控制員的工作。該視圖只呈現HTML - 控制器監聽事件並相應地執行操作。
  • 您的模型似乎知道您的意見。模型層應該對視圖層有最少的知識(可能註冊爲observers)。保持你的模型乾淨,關鍵點,我的意思是業務點 - 業務邏輯。在js應用程序中,您可能只是代理服務器端的模型層,但重要的是讓您的模型保持業務邏輯,而不是其他任何東西。應用程序邏輯是控制器作業