2010-06-14 2 views
6

tl; dr: Come si implementa MVC in JavaScript in modo pulito?Model-View-Controller in JavaScript

Sto cercando di implementare MVC in JavaScript. Ho cercato su Google e riorganizzato con il mio codice innumerevoli volte ma non ho trovato una soluzione adeguata. (Il codice semplicemente non "sembra giusto".)

Ecco come me ne occuperò proprio adesso. È incredibilmente complicato ed è un problema lavorare con (ma ancora meglio della pila di codice che avevo prima). Ha brutte soluzioni alternative che sconfiggono lo scopo di MVC.

Ed ecco, il disordine, se siete veramente coraggiosi:

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

Come si fa a implementare MVC in JavaScript in un modo più pulito? Come posso migliorare questo sistema? O è questa la strada completamente sbagliata, dovrei seguire un altro schema?

+0

(quattro anni più tardi) Utilizzare AngularJS. –

+1

Se stavi solo cercando di capire come funziona MVC in Javascript, chiedere come implementarlo è perfettamente ragionevole. Troppi sviluppatori utilizzano ora i framework senza realmente capire come funzionano. – NobodyReally

risposta

0

Per essere onesti, MVC non è adatto per Javascript. Può supportare i fondamenti di base del design, certo - puoi creare pseudoclass per agire come controller o modelli, supportare l'ereditarietà di base e puoi farli manipolare o creare un numero qualsiasi di elementi DOM, ma c'è un prezzo che paghi per quello - in testa, accessibilità e usabilità.

A mio parere, considero Javascript più di un aumento - la mentalità KISS esiste per una buona ragione. Se sei interessato a modi migliori per organizzare il tuo codice, c'è sempre l'opzione relativa alla funzionalità relativa al packaging in moduli (sic) e l'astrazione di porzioni appropriate. Ad esempio, creare una factory per eseguire una gestione delle richieste AJAX più complessa o una pseudoclass per gestire l'elaborazione di tipi di dati simili. Usando una funzione base standard per i controller, un altro per i modelli, ecc., Come prototipi per nuove istanze di quegli oggetti possono ottenere funzionalità simili ... ma, ancora una volta, è un po 'andare contro il rigore di Javascript.

Tuttavia, se sei bloccato sull'idea MVC solo per il gusto di struttura, prendere in considerazione qualcosa di simile al seguente:

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

E 'estremamente semplice, ma si ottiene l'idea. Il codice modulare è la chiave ... in JS, è più importante che forzare l'applicazione (o la lingua) per adattarla a un determinato stile.

+1

Sono completamente d'accordo con il tuo punto, ma la mia applicazione è complicata (è un'applicazione di Gmail - non così grande, ma il punto rimane). Anche organizzato in modo simile al modello nel tuo post, il codice era un disastro; Ho dovuto trovare un modello organizzativo, quindi non sono diventato matto. Non ho bisogno di aderire a MVC se è una seccatura implementare (bene), ma in tal caso ho bisogno di un modello di sostituzione. –

6

Esistono almeno un paio di framework MVC consolidati e utilizzabili per JavaScript JavaScriptMVC e pureMVC. Ce ne sono probabilmente di più Ho usato JavaScriptMVC per applicazioni basate su browser e Air e continuo a tornare ad esso - ha i suoi problemi, ma ho trovato che sia abbastanza utile.
Ci sono anche altre soluzioni, date un'occhiata allo Sammy, una cosa nuova di cui ho sentito parlare bene. Non mi sono mai abituato, ma intendo provare presto. Non ne so abbastanza per descriverlo correttamente, ma a me sembra un front controller che funziona su route, un sistema di template e archivi di dati di ReSTful. Non sono sicuro che sia MVC ma abbia ingredienti simili.

Devo non essere d'accordo con mway's answer. MVC può essere un po 'diverso da implementare in JavaScript, ma i suoi benefici sono molto importanti per organising this mess. Gli schemi di progettazione solitamente associati ai linguaggi OO non escono dalla finestra solo perché js non è basato sulla classe.

Direi che MVC è più adatto per le app JavaScript che per le applicazioni basate su richiesta (lato server).Questi oggetti possono rimanere inutilizzati per un po 'in una app JavaScript di una pagina - minuti se non ore - e avere un modo ben organizzato di organizzare la loro interazione renderà il tuo codice molto più robusto e facile da gestire. There are books on the subject.

Un paio di altri punti relativi al codice che hai postato.

  • Gli oggetti di visualizzazione hanno la responsabilità di applicare i listener di eventi agli elementi DOM. Questo è il lavoro del controllore. La vista mostra solo l'HTML: il controller ascolta gli eventi e agisce di conseguenza.
  • I tuoi modelli sembrano conoscere le tue opinioni. Il livello del modello dovrebbe avere una conoscenza minima del livello vista (forse registrato come observers). Mantieni il tuo modello pulito e al punto, intendo il punto di business - la logica del business. Nelle app js potresti semplicemente passare a un livello di modello lato sever, ma è importante per il tuo equilibrio mantenere il tuo modello alla logica di business e nient'altro. La logica dell'applicazione è il lavoro dei controllori