2011-08-19 27 views
9

Attualmente stiamo dando il via al nostro primo progetto Backbone.js qui al lavoro. In effetti è il nostro primo grande progetto JavaScript a parte le strane cose di jQuery.Qual è un buon modo per creare un progetto Backbone.js?

In ogni caso, abbiamo problemi con l'architettura per le nostre cose. Qual è il modo migliore per ordinare qualcosa?

Abbiamo iniziato ad avere tutto in file separati suddivisi in cartelle per; viste, modelli, collezioni e router e quindi includiamo tutto nel nostro index.html. Il problema, tuttavia, è che questo ci lascia con la necessità di controllare l'evento pronto per il documento in ogni file. È questo il modo migliore per farlo?

Ecco un esempio:

Questo è il file chiamato PageModel, la prima linea sembra sbagliato ...

$(function(){ 
    app.models.Page = Backbone.Model.extend({ 
    //stuff 
    }); 
}); 

Poi, nel nostro index.html abbiamo:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html> 
    <head> 
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
     <title></title> 

     <link href="assets/css/style.css" rel="stylesheet" type="text/css" /> 

     <script type="text/javascript"> 
      var app   = app     || {}; 

      app.models   = app.models   || {}; 
      app.collections = app.collections  || {}; 
      app.views  = app.views   || {}; 
      app.routers  = app.collections  || {}; 
      app.templates  = app.templates  || {}; 

      app.models.griditems = app.models.griditems || {}; 
      app.views.griditems = app.views.griditems || {}; 
     </script> 

     <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" type="text/javascript"></script> 
     <script src="assets/js/libs/json2.js" type="text/javascript"></script> 
     <script src="assets/js/libs/underscore-1.1.7.min.js" type="text/javascript"></script> 
     <script src="assets/js/libs/backbone-0.5.3.min.js" type="text/javascript"></script> 

     <script src="assets/js/models/GridItemModel.js" type="text/javascript"></script> 
     <script src="assets/js/models/GalleryGridItemModel.js" type="text/javascript"></script> 
     <script src="assets/js/models/NewsGridItemModel.js" type="text/javascript"></script> 
     <script src="assets/js/models/VideoGridItemModel.js" type="text/javascript"></script> 

     <script src="assets/js/collections/GridCollection.js" type="text/javascript"></script> 

     <script src="assets/js/templates/Submenu.js" type="text/javascript"></script> 
     <script src="assets/js/templates/GalleryGridItemTemplate.js" type="text/javascript"></script> 

     <script src="assets/js/views/GridView.js" type="text/javascript"></script> 
     <script src="assets/js/views/GridItemView.js" type="text/javascript"></script> 
     <script src="assets/js/views/GalleryGridItemView.js" type="text/javascript"></script> 
     <script src="assets/js/views/VideoGridItemView.js" type="text/javascript"></script> 

     <script src="assets/js/routers/Router.js" type="text/javascript"></script> 

     <script src="assets/js/Application.js" type="text/javascript"></script> 
    </head> 

    <body> 
    </body> 
</html> 
+0

Non è necessario definire modelli/collezione/viste/router sull'evento DOMReady. L'unica cosa che deve essere chiamata solo quando il dom è pronto è 'Backbone.history.start()'. – shesek

risposta

4

Questo è struttura che utilizziamo nei nostri progetti Backbone

<!-- Libs Section --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery-1.5.2.min.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.validate.min.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.maskedinput-1.3.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.mousewheel.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/jquery.scrollpane.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/fileuploader.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/modernizr.min.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/json2.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/underscore-min.js")"></script> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/libs/backbone-min.js")"></script> 
<!-- Libs Section --> 

<!-- Core Section --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/config.js")"></script> <!-- Global configs --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/core.js")"></script> <!-- Core methods for easier working with views, models and collections + additional useful utils --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/app.js")"></script> <!-- Application object inherites core.js as prototype --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/renisans.js")"></script> <!-- Project Object. Creates Namespace and Extends it with project specific methods --> 
<!-- Core Section --> 

<!-- Routers Section --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/routers/workspace.js")"></script> 
<!-- Routers Section --> 

<!-- Models Section --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/models/profile.js")"></script> 
    ... 
<!-- Models Section --> 

<!-- Collections Section --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/collections/messages.js")"></script> 
    ... 
<!-- Collections Section --> 

<!-- Views Section --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/views/workspace.js")"></script> 
    ... 
<!-- Views Section --> 

<!-- Localization Section --> 
    <script type="text/javascript" src="@Url.Content("~/Content/static/js/localizations/ru_RU.js")"></script> 
<!-- Localization Section --> 

<!-- Init Section --> 
    <script type="text/javascript"> 
     $(function() { 
      Rens.container = $('.l-wrapper'); // Some parameters 
      Rens.init({ 
       Localization: LocalizationStrings || {}, // Object with localization strings 
       Profile: { 
        // Bootstraping initial data to Profile model 
       } 
      }); 
     }); 
    </script> 
<!-- Init Section --> 

contenuto di app.js

var App = function() { 
     this.Views = {}; 
     this.Routers = {}; 
     this.Models = {}; 
     this.Collections = {}; 
     this.User = {}; 

     this.router = null; 
     this.view = null; 
     this.baseLocation = null; 

     this.beforeInit = function() {}; 
     this.afterInit = function() {}; 

     this.init = function(initData) { 
      if (typeof(this.beforeInit) === 'function') { 
       this.beforeInit.apply(this, arguments); 
      } 

      if (this.Views.Workspace) { 
       this.view = new this.Views.Workspace(); 
      } 
      this.baseLocation = window.location.href.replace(/[?#].*/, '') == Config.web.host; 

      if (this.Routers.Workspace) { 
       this.router = new this.Routers.Workspace(initData); 
      } 
      this.view && this.view.setListeners && this.view.setListeners(); 
      Backbone.history.start(); 

      if (typeof(this.afterInit) === 'function') { 
       this.afterInit.apply(this, arguments); 
      } 
     }.bind(this); 
    }; 

App.prototype = Core; 

e contenuto del renisans.js

var Rens = new App(); 

$.extend(Rens, { 
    container: null, 

    Error: function(data) { 
     // Handling error 
    }, 

    Localization: function(dictionary) { 
     return { 
      get: function(name) { 
       var argumentsList = Array.prototype.slice.call(arguments), 
        strings = argumentsList.slice(1), 
        text = this[name]; 

       if (text && strings.length) { 
        $(strings).each(function(i, string) { 
         var reg = new RegExp('\\$' + i, 'go'); 

         text = text.replace(reg, string); 
        }); 
       } 
       return text || 'SLB.Localization.' + name + ' not found!'; 
      }.bind(dictionary) 
     } 
    }, 

    formatDate: function(rawDate) { 
     var timestamp = /\d+/.exec(rawDate)[0], 
      date = Rens.DateUTC(timestamp), 
      months = Rens.Localization.get('months'); 

     return { 
      date: date, 
      fullDate: [date.dd, months[date.mm], date.hh].join(' '), 
      shortDate: [date.dd, date.MM, date.hh].join('.') 
     }; 
    }, 

    beforeInit: function(initData) { 
     this.Localization = new this.Localization(initData.Localization); 
    } 
}); 

contenuto anche semplificata dei modelli/profile.js

Rens.Models.Profile = Backbone.Model.extend({ 
    ... 
}); 
+0

Ehi! Grazie per la risposta. Ma come gestisci il codice nel tuo file di esempio qui? Hai anche una funzione pronta per il documento? Sarebbe fantastico se potessi dare un'occhiata a come hai strutturato il file di progetto renisans.js e app.js. – Joel

+0

documento pronto all'uso solo una volta solo per l'inizializzazione –

+0

Grazie a @ant_Ti per un ottimo post, risolto un sacco di problemi per me! Un paio di domande però. Che tipo di materiale usi in Core.js da allora? App.prototype = Core ;? E inoltre, perché hai sia Application.js che renisans.js? – Joel

4

Se si sta creando un applicazione di questa forma, consiglio vivamente di utilizzare il caricamento dinamico delle risorse, come javascript e altro.

Sono disponibili diverse opzioni per questo:

Io stesso ho alcuna esperienza con LABjs, ma ho usato richiedere. js in piccoli progetti per me stesso. Ma devono ancora usarlo in un grande progetto.

i vantaggi di un tale sistema:

  • è possibile lavorare con le dipendenze, e i vostri modelli o punti di vista sarà caricato solo quando sono richiesti da un'altra parte del codice. non tutto all'inizio.
  • require.js fornisce anche funzionalità per la minimizzazione e l'aggregazione del codice in base alle dipendenze specificate.
  • require.js ha alcuni piccoli plugin per il caricamento in file di testo (se si utilizza un sistema di template può essere utile o un plugin per definire l'ordine in cui i file devono essere caricati.
  • e require.js ha anche una versione speciale per working together with jquery e i suoi moduli.(ma non sei obbligato a usare questo, puoi caricare manualmente jquery trogolo)

dovrai avvolgere i tuoi modelli/viste/... in moduli in modo che require.js possa caricarli dinamicamente . Ho chiesto informazioni su questo qui in overflow dello stack la scorsa settimana ... puoi trovare le informazioni su come farlo here

Ti suggerisco di leggere lo 'getting started with require.js' e vedere se hai voglia di usarlo.

perché lavorare con tutti i modelli/viste/... in file separati è abbastanza utile in fase di sviluppo, ma è decisamente sconsigliato quando si entra in produzione. meno richieste devono essere inviate dal browser al server, meglio è.

+1

Sono assolutamente d'accordo sull'utilizzo di un caricatore di risorse. Usiamo require.is e lo consiglio vivamente – timDunham

Problemi correlati