2011-12-05 62 views
7

我剛剛開始使用Backbone。我瀏覽了前兩個PeepCode屏幕視頻,這些視頻非常棒,現在我正在深入研究未來應用的快速分離(無需服務器端)模型。骨幹設計

這是我正在尋找(大致)。一系列五個文本框 - 讓我們調用這些Widgets。每個Widget輸入在被選中時將顯示一個窗格,該窗格顯示與該Widget關聯的任務,並允許用戶創建新任務或銷燬現有任務。

在這一點上,我想我有以下型號:

Widget 
Task 

以下集合:

Tasks 
Widgets 

下面的意見(這是它得到毛茸茸的!)

WidgetListView 
    - Presents a collection of Widgets 
WidgetView 
    - sub-view of WidgetListView to render a specific Widget 
TaskPaneView 
    - Presented when the user selects a Widget input 
TaskCreateView 
    - Ability to create a new Task associated with selected Widget 
TaskListView 
    - Presents a collection of Tasks for the given widget 
TaskView 
    - Displays Task detail - sub-view of TaskListView 

假設這是合理的,訣竅就變成了如何在WidgetView爲se時顯示TaskPaneView lected。此外,TaskPaneView應該如何呈現TaskCreateViews和TaskListViews。

這裏真正的問題是:一個級聯是否跨視圖呈現事件?允許Root視圖瞭解子視圖並明確呈現它們嗎?這應該是事件驅動的嗎?

道歉,如果這是一個開放式的問題,只希望有人會看到以前類似的東西,並能指出我在正確的方向。

謝謝!

+1

@Luc Perkins建議Backbone Aura,你可能想要檢查一下Marionette。木偶可能比Aura更成熟 –

+0

我認爲TaskCreateView和TaskPaneView是不必要的。 TaskCreateView特別不應該在那裏,因爲它沒有任何模型來表示。將任務創建合併到TaskListView本身中。也許一個輸入控件可以讓用戶添加新的任務。當用戶按Enter鍵時,將它添加到Tasks集合中。我假設您正在偵聽收集上的添加事件,以便您可以將新創建​​的TaskView添加到TaskListView。只要用戶關注WidgetView,就可以調出TaskListView。 – Vishal

回答

15

絕對讓它成爲事件驅動。另外,儘量不要創建緊密耦合的視圖。鬆耦合將使您的代碼更易於維護和靈活。

退房這個職位上的事件聚合模式,骨幹:

http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/

簡短的版本是,你可以這樣做:

var vent = _.extend({}, Backbone.Events); 

,並使用vent.trigger和vent.bind控制你的應用程序。

+0

非常有趣。我會回來一個upvote。任何想法是否對於具有子視圖的根視圖來說很酷?例如 - TaskPaneView - 哪個房子創建和列表甚至有意義? – Cory

+1

完全沒有問題,嵌套視圖是非常有可能的,我只能說自己說我經常使用它們,最簡單的例子是有一本書目錄,一個ListView和每個項目作爲它自己的視圖,但它可能會進一步惡化。 – Sander

+1

它很酷,因爲它的工作原理。這不是很酷,因爲它會更難維護你的代碼。模塊化並使用事件觸發渲染。如果你使用事件agg模式,你可以做一些類似vent.trigger('create',model);這會將模型傳遞給綁定回調(在這種情況下:呈現視圖的函數)。在這種情況下,您的創建視圖現在是您可以在任何地方調用的應用程序的可重用組件。 –

0

從傳統的MVC角度來看,您的觀點會響應相關模型的變化。

//initialize for view 
initialize : function() { 
    this.model.on("change", this.render(), this); 
} 

這裏的想法是,無論何時視圖的模型被改變,它都會呈現自己。

另外或另外,如果您更改視圖上的某些內容,您可以觸發控制器偵聽的事件。如果控制器也創建了其他模型,它可以用一些有意義的方式修改它們,然後如果您正在傾聽對模型的更改,視圖也會改變。

+1

有趣的是,你可以擴展Backbone.Events。我自己使用從我這裏得到的'Pure JS pub/sub'實現: http://jsperf.com/pubsubjs-vs-jquery-custom-events/26 我真的建議檢查一下任何人到pub/sub或javascript表現。 – Mosselman

+1

其實,你不能擴展Backbone.Events。這只是一個簡單的散列,您可以添加到自定義對象的原型中,以使其能夠發送和接收事件。 –

0

對Chris Biscardi's的解答與其相似。下面是我有:

您(從骨幹網應用的範圍,只要它能夠被訪問並不一定是全球性的)創建一個全局變量接線員:

Dispatcher = _.extend({}, Backbone.Events); 

調度人員會幫助你執行訂閱的回調事件並不特別由模型或集合中的更改觸發。而且很酷的事情是Dispatcher可以執行Backbone應用內部或外部的任何功能。

您訂閱事件使用視圖中的綁定()或應用程序的任何部分:

:在應用程序的其他視圖或部分

Dispatcher.bind('editor_keypress', this.validate_summary); 

然後,你使用觸發器()觸發新的事件

Dispatcher.trigger('redactor_keypress'); 

使用調度程序的美妙之處在於它的簡單性和能夠爲同一事件訂閱多個偵聽器(例如,不同Backbone視圖中的回調)。

12

預P.S:我已經爲你與我下面寫的代碼要點:我與由其他答案建議的發佈/訂閱(「觀察者模式」)同意 https://gist.github.com/2863979

。然而,我也會使用Require.js和Backbone的強大功能。

艾迪奧斯馬尼寫了一些偉大的!

http://addyosmani.com/resources/essentialjsdesignpatterns/book/ http://addyosmani.com/writing-modular-js/ http://addyosmani.github.com/backbone-fundamentals/

關於與骨幹一起使用AMD(在Require.js實現)很酷的事情是,你解決一些問題,你用」:關於JavaScript的設計模式和有關建築物主幹應用程序資源通常有。

通常你會定義類,這些存儲在某種命名空間中的方式,如:

MyApp.controllers.Tasks = Backbone.Controller.extend({}) 

這是好的,只要你在一個文件中定義的大多數事情,當你開始添加越來越多不同的文件混合它變得不那麼強大,你必須開始關注你如何加載不同的文件,controllers\Tasks.jsmodels\Task.js之後等等。當然你可以按照正確的順序編譯所有的文件等,但它遠非完美。

最重要的是,非AMD方式的問題在於,您必須更緊密地將視圖嵌套在對方內。可以這樣說:

MyApp.classes.views.TaskList = Backbone.View.extend({ 
    // do stuff 
}); 

MyApp.views.App = Backbone.View.extend({ 
    el: '#app', 
    initialize: function(){ 
     _.bindAll(this, 'render'); 
     this.task_list = new MyApp.classes.views.TaskList();  
    }, 

    render: function(){ 
     this.task_list.render(); 
    } 
}); 

window.app = new MyApp.views.App(); 

一切都很好,但這可以成爲一場噩夢。

隨着AMD可以定義一個模塊,並給它一些依賴關係,如果你有興趣在此工作方式讀取上面的鏈接,但上面的例子是這樣的:

// file: views/TaskList.js 
define([], function(){ 

    var TaskList = Backbone.View.extend({ 
     //do stuff 
    }); 

    return new TaskList(); 
}); 

// file: views/App.js 
define(['views/TaskList'], function(TaskListView){ 

    var App = Backbone.View.extend({ 
     el: '#app', 

     initialize: function(){ 
      _.bindAll(this, 'render'); 
     }, 

     render: function(){ 
      TaskListView.render(); 
     } 
    }); 

    return new App(); 
}); 

// called in index.html 
Require(['views/App'], function(AppView){ 
    window.app = AppView; 
}); 

請注意,在你會返回實例的意見的情況下,我的收藏就此別過,但對於模型我回班:

// file: models/Task.js 
define([], function(){ 

    var Task = Backbone.Model.extend({ 
     //do stuff 
    }); 

    return Task; 
}); 

這似乎有點吃不消起初,人們可能會覺得「哇,這是矯枉過正」。但是,當你必須使用相同的對象在許多不同模塊的真正威力變得明確,比如集合:

// file: models/Task.js 
define([], function(){ 

    var Task = Backbone.Model.extend({ 
     //do stuff 
    }); 

    return Task; 
}); 

// file: collections/Tasks.js 
define(['models/Task'], function(TaskModel){ 

    var Tasks = Backbone.Collection.extend({ 
     model: TaskModel 
    }); 

    return new Tasks(); 
}); 

// file: views/TaskList.js 
define(['collections/Tasks'], function(Tasks){ 

    var TaskList = Backbone.View.extend({ 
     render: function(){ 
      _.each(Tasks.models, function(task, index){ 
       // do something with each task 
      }); 
     } 
    }); 

    return new TaskList(); 
}); 


// file: views/statistics.js 
define(['collections/Tasks'], function(Tasks){ 

    var TaskStats = Backbone.View.extend({ 
     el: document.createElement('div'), 

     // Note that you'd have this function in your collection normally (demo) 
     getStats: function(){ 
      totals = { 
       all: Tasks.models.length 
       done: _.filter(Tasks, function(task){ return task.get('done'); }); 
      }; 

      return totals; 
     }, 

     render: function(){ 
      var stats = this.getStats(); 

      // do something in a view with the stats. 
     } 
    }); 

    return new TaskStats(); 
}); 

注意,「任務」的對象恰恰是在這兩種觀點是相同的,所以同樣的車型,狀態等。這比在一個時間點創建Tasks集合的實例然後始終參考整個應用程序要好得多。

至少對我來說,使用Require.js和Backbone已經帶走了一個令人費解的巨大難題,在哪裏實例化了什麼。爲此使用模塊非常有用。我希望這也適用於你的問題。

p.s.還請注意,您也可以將Backbone,Underscore和jQuery作爲模塊添加到您的應用中,儘管您不需要,但可以使用普通腳本標記加載它們。

+0

偉大的答案男人,你讓我的一天。 – mamoo

+0

@mamoo謝謝!很高興我能幫上忙。謝謝你讓我知道你喜歡它。 – Mosselman

+0

很好的答案。另外,Perry鴨嘴獸岩石。 – jerrygarciuh

1

對於具有這種複雜性的東西,我可能會推薦使用Backbone Aura,它還沒有穩定的版本。 Aura本質上允許您在單個頁面上運行多個完全自包含的Backbone應用程序,稱爲「小部件」,這可能有助於解開並平滑某些模型/視圖邏輯。