2014-05-28 6 views
7

sto praticando con OO JavaScript, facendo una sorta di web-app per la visualizzazione di Manga (fumetti)OO Javascript - Dovrei lasciare che una classe si aggiunga al DOM o lasciare che restituisca un elemento per poi aggiungerlo al DOM?

In questo momento ho un paio di classi:

  • SearchResult
  • Manga (generato da dati fuori del risultato della ricerca)
  • capitolo (contenuta all'interno Manga)
  • Pagina (contenuta nel capitolo)
  • Immagine (contenuta all'interno di Pagina)

Aggiungo il risultato della ricerca al DOM generando l'html dell'elemento e quindi aggiungendolo con jQuery.

Questo è dove la mia domanda è disponibile in:

Devo generare html (o un elemento di jQuery DOM) e restituire questo da una funzione nella classe e quindi aggiungere questo elemento al di fuori della classe o sarebbe più saggio dare alla classe un riferimento al contenitore in cui inserire gli elementi e lasciarli mettere gli elementi in quel contenitore aggiungendo?

Quindi questo ?:

function(data, result, response) { 
    var 
    $resultContainer = $('<div/>', {class: 'row-fluid'}), 
    maxResults = 10; 

    for(var i in data) { 
    if(i == maxResults) { 
     break; 
    } 
    data[i].manga = Manga(data[i]); 
    var res = new SearchResult(data[i]); 
    res.setMyContainerElement($resultContainer); 
    res.addResultToDOM(); 
    } 
} 

O questo ?:

function(data, result, response) { 
    var 
    $resultContainer = $('<div/>', {class: 'row-fluid'}), 
    maxResults = 10; 

    for(var i in data) { 
    if(i == maxResults) { 
     break; 
    } 
    data[i].manga = Manga(data[i]); 
    var res = new SearchResult(data[i]); 
    $resultContainer.append(res.getHTML()); 
    } 
} 

In questi esempi "Dati" la variabile è dati da una chiamata AJAX che restituisce un JSON-stringa contenente i risultati, attualmente non c'è limite alla quantità di risultati restituiti, quindi l'ho impostato in modo hard-coded, lo aggiungerò quando andrò più in dettaglio sul lato server, ma per ora ciò andrebbe bene mentre lavoro sul front-end.

Se sono necessarie ulteriori informazioni, fatemelo sapere, aggiornerò volentieri con tutte le informazioni che potrei aver perso o che è necessario, se disponibile.

+4

In teoria, il codice è più riutilizzabile se si restituisce la struttura dalla funzione * worker * e si lascia che la funzione * manager * che ha deciso di decidere cosa fare con esso. cioè "I lavoratori lavorano e gestiscono i manager". Passare il contenitore lungo l'albero del codice aggiunge dipendenze :) Non è facile, ma l'approccio migliore è pensare che ogni funzione venga scritta per qualcun altro e si desidera essere il più utile possibile. –

+0

Questo è quello che ho pensato e fatto fino ad ora, ma ho pensato a cosa sarebbe successo se tu, per qualsiasi ragione folle, dovessi cambiare il modo in cui la classe ha funzionato e avrebbe prodotto qualcosa che non si sarebbe aspettato da nessuna il codice stava usando l'output della classe, questo significherebbe un sacco di refactoring. Modifica: Anche se di solito dovresti evitare questo, dato che c'è un sacco di codice che dipende dall'output di certe funzioni. Edit2: @TrueBlueAussie Hai ragione, in questo modo funziona più come un'API, di sorta, o in una vera e propria fabbrica, emettendo parti che devono essere utilizzate da processi esterni. – Magikaas

+0

Se si modifica la struttura dei dati, ovviamente è necessario un refactoring, ma è preferibile spostare le decisioni/dipendenze fino ad un livello inferiore. Se vuoi essere forzato a rivedere il codice di alto livello che dipende dalla forma dei dati. –

risposta

3

Moving commenti di rispondere, come la questione è prevalentemente a base di opinione e può anche ottenere chiuso :)

In teoria il codice è più riutilizzabile se si torna la struttura dalla funzione dei lavoratori e lasciare che la funzione di manager che chiamato decidere cosa fare con esso. cioè "I lavoratori lavorano e gestiscono i manager". Passare il contenitore lungo la struttura del codice aggiunge dipendenze :)

Non è facile, ma l'approccio migliore è pensare che ogni funzione venga scritta per qualcun altro e si desidera essere il più utile possibile.

Se si modifica la struttura dei dati, ovviamente è necessario un refactoring, ma è preferibile spostare le decisioni/dipendenze fino ad un livello inferiore. Se vuoi essere forzato a rivedere il codice di alto livello che dipende dalla forma dei dati.

Per quanto riguarda i parametri essendo dipendenze:

parametri a funzioni sono solo badder quando causano decisioni da dalla funzione (noto come accoppiamento di comando). I valori per la ricerca e l'elaborazione sono gooder utilizza per i parametri :)

0

Devo generare HTML o un elemento di jQuery DOM

elemento DOM, sicuramente.

Devo restituire questo da una funzione nella classe e quindi aggiungere questo elemento all'esterno della classe o sarebbe più saggio fornire alla classe un riferimento al contenitore in cui inserire gli elementi?

Entrambi gli approcci sono abbastanza soddisfacenti. Quale scegliere dovrebbe dipendere dal fatto che l'istanza della classe sia occupare il contenitore completo.

Se è così, è corretto passare l'elemento contenitore al costruttore e lasciare che il codice di classe faccia tutto ciò che vuole fare con esso. La maggior parte dei widget funziona in questo modo e il metodo è utilizzato favorevolmente dai plugin jQuery che vengono richiamati comunque sugli elementi.

Se la classe crea un singolo elemento e non può essere sicuro di cosa farne, restituirlo sarebbe meglio.Come dici tu,

lasciarlo mettere gli elementi in quel contenitore aggiungendo

non lo rende molto riutilizzabile. Che cosa succede se ora vuoi metterli nel contenitore prepending? La classe non lo sa, dovrebbe semplicemente cedere il suo elemento a te. Quei metodi .setMyContainerElement() e .addResultToDOM() non sono altro che codice di codice, che racchiude i metodi jQuery equivalenti. È meglio restituire la raccolta jQuery e lasciare che il chiamante faccia il .appendTo($containerElement) (o .prependTo($containerElement)?).

+0

Quando ho detto accodando, era un esempio, potevo aggiungere, anteporre, sostituire, qualunque cosa sarebbe richiesta, a seconda di cosa la funzione vuole fare. Ma capisco cosa intendi, potrei usare pure append invece di addResultToDOM, ma dovevo dargli un nome ragionevolmente descrittivo se dovessi aggiungerlo come una funzione alla classe, per ora sono tornato a restituire un jQuery Elemento DOM, che posso quindi utilizzare per il contenuto del mio cuore in qualsiasi codice usando detta classe. – Magikaas

+0

Bene, il punto è: la classe sa cosa è richiesto o dovrebbe coprire tutte le possibilità che il chiamante potrebbe desiderare? – Bergi

+0

Al momento, sarebbe solo necessario restituire un singolo elemento DOM, che rappresenta SearchResult, che potrebbe quindi essere aggiunto a un contenitore per questi risultati di ricerca.Quindi immagino che questo implichi che debba coprire tutte le possibilità? Non ho riflettuto troppo a fondo sull'implementazione e sono ancora abbastanza presto nello sviluppo, creando la struttura delle mie classi e le loro rispettive funzioni. – Magikaas

2

In OOP, sarebbe indietro per restituire un Vista da un modello, quindi ho intenzione di raccomandare a non farlo.

Quello che stai davvero cercando qui è un sistema di template: un modello significa che hai un pezzo di HTML seduto da qualche parte sulla tua pagina, con valore 'segnaposto', e quando sei pronto a stampare il tuo SearchResult, il modello è clonato, inserito nella pagina e i "segnaposti" sono riempiti con i valori effettivi (ad esempio il titolo del fumetto, l'immagine di copertina, ecc.)

Ci sono molti sistemi di template JavaScript. Fuori della parte superiore della mia testa:

  • MustacheJS
  • Manubri
  • DustJS
  • KnockoutJS

Ho esperienza con KnockoutJS così posso darvi un'anteprima di come sarebbe simile in codice (vedi i tag 'data-bind', gestiti da KnockoutJS automaticamente):

<body> 
    <!-- The contents of this DIV will be repeated for each 'manga' in 'mangas' --> 
    <div class="manga-list" data-bind="forEach: mangas"> 
     <!-- This paragraph will be updated with the manga's 'title' value --> 
     <p class="manga-title" data-bind="text: title"></p> 

     <!-- This paragraph will be updated with the manga's 'cover' value (as src) --> 
     <img class="manga-cover" data-bind="attr: {src: cover}" /> 
    </div> 
</body> 
<script> 
    var viewModel = { 
     mangas: ko.observableArray(); 
    }; 
    ko.applyBindings(viewModel); 

    // ... 
    // some code where you get your SearchResult 
    // ... 
    for (var i = 0; i < searchResult.length; i++) 
    { 
     viewModel.mangas.push(searchResult[i]); 
    } 
    // When the FOR loop above runs, your HTML is automatically updated. 
<script> 

Non sono sicuro se sono corretto al 100% sulla sintassi sopra (forse mi manca un personaggio o qualcosa del genere) ma è di gran lunga la mia libreria di binding/templating preferita, ed è piuttosto stravagante da usare.

+0

Uh, 'new SearchResult (data [i])' assomiglia molto a una vista, dove 'data [i] .manga = Manga (data [i])' è il modello. La domanda è se una vista (potrebbe utilizzare modelli o no) dovrebbe applicarli su un determinato elemento DOM o restituire un elemento DOM. – Bergi

+0

Woah, mio ​​male. Vabbè, forse questo permetterà ad altri visitatori di scoprire il potere dei modelli di librairie; mi dispiace, questo è risultato irrilevante. – hbCyber

+0

Nel mio codice, non ho applicato nulla come una struttura MVC, sono ancora abbastanza nuovo per questo tipo di strutture di programmazione OO, quindi applicarle a Javascript OO è al di là delle mie capacità attuali, se si fosse implicito che avessi un sottostante Struttura MVC per gestire queste classi e il loro output. Le classi sono controllori, viste e modelli allo stesso tempo, sarebbe più saggio implementare una struttura MVC a questo tipo di codice (data la mia esperienza) o sarebbe troppo complicato e/o troppo grande da saltare a questo punto? Sono ancora all'inizio del processo di questa applicazione. – Magikaas

0

Tendo a vedere viste personalizzate proprio come se fossero elementi DOM nativi e questo si allinea molto bene con i componenti Web.

Quando si installa un nuovo elemento DOM, non è l'elemento stesso che ha la responsabilità di eseguire il rendering nel suo contenitore; altrimenti l'elemento dovrebbe conoscere il contesto in cui viene reso e sarebbe una pessima forma di accoppiamento.

Come ha detto @Bergi, è meno dannoso lasciare che il componente si renda nel suo contenitore se è progettato per occupare tutto lo spazio del contenitore. Tuttavia, questa pratica spesso porta ad avere un elemento contenitore aggiuntivo al solo scopo di posizionare la vista.

In breve, direi che se il codice della vista non è progettato per migliorare un elemento esistente, si dovrebbe evitare di dargli la responsabilità di eseguire il rendering nel proprio contenitore. La flessibilità che si ottiene lasciando l'attività di rendering fino al codice chiamante supera facilmente la complessità aggiunta.

PS: DOM vs HTML strings = DOM a meno che non vi siano implicazioni di prestazioni significative e siete disposti a sacrificare in termini di flessibilità.

Problemi correlati