2010-06-14 9 views
6

tl; dr: Jak jeden wdrożyć MVC w JavaScript w czysty sposób?Model-widok kontroler w JavaScript

Próbuję zaimplementować MVC w JavaScript. Przeszukałem go i zreorganizowałem z moim kodem niezliczoną ilość razy, ale nie znalazłem odpowiedniego rozwiązania. (Kod po prostu nie "czuje się dobrze").

Oto, jak to teraz robię. Jest to niewiarygodnie skomplikowane i sprawia ból (ale wciąż lepszy od stosu kodu, który miałem wcześniej). Ma brzydkie obejścia tego rodzaju, które pokonują cel MVC.

A oto bałagan, jeśli jesteś naprawdę odważny:

// 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 
    }; 
} 

jaki sposób można wdrożyć MVC w JavaScript w czystszym sposób? Jak mogę ulepszyć ten system? Czy jest to całkowicie niewłaściwa droga, czy powinienem zastosować inny wzór?

+0

(cztery lata później) Użyj AngularJS. –

+1

Jeśli próbujesz zrozumieć, jak działa MVC w JavaScript, to pytanie, jak go wdrożyć, jest całkowicie uzasadnione. Zbyt wielu programistów używa teraz frameworków bez zrozumienia, jak działają. – NobodyReally

Odpowiedz

0

Szczerze mówiąc, MVC nie jest dobrze dostosowane do Javascript. Może obsługiwać podstawowe zasady projektowania, oczywiście - możesz tworzyć pseudoklasy, które działają jako kontrolery lub modele, obsługują podstawowe dziedziczenie i możesz nim manipulować lub tworzyć dowolną liczbę elementów DOM, ale jest cena, którą za to zapłacisz - pod względem kosztów, dostępności i użyteczności.

Moim zdaniem, uważam Javascript za bardziej ulepszony - mentalność KISS istnieje z dobrego powodu. Jeśli interesują Cię lepsze sposoby na uporządkowanie kodu, zawsze istnieje możliwość przypisania funkcji związanych z pakietami do modułów (sic) i, odpowiednio, wydzielenia części. Na przykład tworzenie fabryki umożliwiającej bardziej złożone zarządzanie żądaniami AJAX lub pseudoklasę obsługi przetwarzania podobnych typów danych. Używanie standardowej funkcji bazowej dla kontrolerów, innej dla modeli itp., Ponieważ prototypy nowych instancji tych obiektów mogą osiągnąć podobną funkcjonalność ... ale znowu jest to wbrew ziarnu JavaScriptu.

Jednakże, jeśli utkniesz na idei MVC właśnie ze względu na strukturę, należy rozważyć coś jak następuje:

;(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); 

jest to bardzo proste, ale masz pomysł. Kod modułowy jest kluczem ... w JS jest to ważniejsze niż wymuszanie na aplikacji (lub języku) określonego stylu.

+1

Całkowicie zgadzam się z twoją uwagą, ale moja aplikacja jest skomplikowana (jest to aplikacja e-mailowa w Gmailu - nie tak duża, ale punkt pozostaje). Nawet zorganizowany podobnie jak model w twoim poście, kod był bałaganem; Musiałem znaleźć jakiś model organizacji, więc nie zwariowałem. Nie muszę stosować się do MVC, jeśli jest to kłopot do zaimplementowania (dobrze), ale w tym przypadku potrzebuję zastępczego wzorca. –

6

Istnieje kilka ustalonych i użytecznych frameworków MVC dla JavaScript JavaScriptMVC i pureMVC. Prawdopodobnie istnieje więcej. Użyłem JavaScriptMVC dla aplikacji opartych na przeglądarce i Air i wracam do niego - ma swoje problemy, ale uważam, że jest całkiem użyteczny.
Są też inne rozwiązania, spójrz na Sammy, nową rzecz, o której słyszałem dobre rzeczy. Nie wykorzystałem się, ale zamierzam wkrótce spróbować. Nie wiem wystarczająco dużo o tym, aby go poprawnie opisać, ale wydaje mi się, że to front kontroler, który działa na trasach, systemie szablonów i magazynach danych ReST. Nie jestem pewien, czy to MVC, ale ma podobne składniki.

Nie zgadzam się z mway's answer. MVC może być nieco inny do implementacji w JavaScript, ale jego zalety są bardzo ważne dla organising this mess. Wzorce projektowe zwykle związane z językami OO nie wychodzą poza okno tylko dlatego, że js nie jest oparty na klasach.

Powiedziałbym, że MVC jest bardziej odpowiedni dla aplikacji JavaScript niż dla aplikacji na żądanie (po stronie serwera).Obiekty te mogą się zawiesić na jakiś czas w aplikacji JavaScript na jedną stronę - minuty, jeśli nie godziny - a dobrze zorganizowany sposób organizacji ich interakcji sprawi, że twój kod będzie znacznie bardziej wytrzymały i łatwiejszy w obsłudze. There are books on the subject.

Kilka innych uwag dotyczących kodu, który wysłałeś.

  • Obiekty widoku są odpowiedzialne za stosowanie detektorów zdarzeń w elementach DOM. To jest zadanie kontrolera. Widok po prostu renderuje HTML - kontroler nasłuchuje zdarzeń i działa odpowiednio.
  • Twoje modele wydają się znać Twoje poglądy. Warstwa modelu powinna mieć minimalną wiedzę na temat warstwy widoku (być może jest rejestrowana jako observers). Trzymaj swój model czysty i do rzeczy, mam na myśli punkt biznesowy - logikę biznesową. W aplikacjach js może po prostu być proxy dla warstwy modelu bocznego, ale ważne jest, aby zachować zdrowy rozsądek modelu logiki biznesowej i nic więcej. Logika aplikacji to zadanie kontrolera: