2012-09-06 513 views
4

我正在研究一個大的Backbone.js應用程序。該代碼採用模塊化結構,使用require.js。 現在我看到很多的骨幹代碼和教程這樣做:將變量賦值給Backbone.js中的窗口對象

window.app = (window.app || {}); 

後,他們將指派模型定義和集合實例到全局對象,像這樣:

Task = Backbone.Model.extend({ /*...*/ }); 
Tasks = Backbone.Collection.extend({ /*...*/ }); 

window.app.Task = Task; 
window.app.Tasks = new Tasks(); 
// do this with all your models and collections 

我喜歡這種方法對於其簡單性以及無需處理何時何地實例化集合。但不知怎的,首先使用require.js將所有代碼分配到一個全局變量(除了全局變量通常是javascript中的錯誤代碼風格之外)之後,將代碼分離成微小的比特似乎是錯誤的。

那麼你對此有什麼看法,這種方法有哪些優缺點?你如何處理Backbone中的對象?

回答

6

首先它不是那麼大,污染您的全局命名空間,你可以在自己的名稱空間包裝所有模型中的一個問題:

app = (app || {}); 
app.Task = Backbone.Model.extend({ /*...*/ }); 
app.Tasks = Backbone.Collection.extend({ Model:app.Zask }); 

當談到requirejs這取決於大小的項目。我認爲對於較小的項目你可以沒有。使用requirejs的好處並不在於防止名稱空間污染,它的可維護性更好,因爲您始終可以看到模塊的依賴關係。你可以編寫更好的單元測試,因爲你可以測試一個模塊和mock out all its dependencies。因此,我們從重建像上面的例子中的結構的大型骨幹應用弄成這個樣子:

型號/ Task.js

define(function() { 
    return Backbone.Model.extend({ /*...*/ }); 
}); 

收藏/ Tasks.js

define([models/Task], function (Task) { 
    return Backbone.Collection.extend({ Model:app.Task }); 
}); 

app.js

define([collections/Tasks], function (Tasks) { 
    var tasks = new Tasks(); 
    tasks.fetch(); 
}); 
+2

在requirejs中仍然使用'app'變量是否是傳統的? –

1

我不同意全局變量在javascript中不好用;你需要大多數語言的全局變量。導入內容後,您需要能夠引用它。類似Java的語言只是把所有的類名放到一個巨大的全局堆上;但你永遠不會意識到這是因爲在這些語言中,類(類名,類引用)不是變量。

在JavaScript類中(或假裝模仿類的東西)只是您分配給變量的對象。所以,你要確保你可以在代碼的其他部分引用它們。

現在,實際上在您的示例中,您將模型定義和集合實例(可能是單例)分配給全局範圍。對於模型定義,我會說這是正確且唯一的方法(可能會添加一些命名空間,如window.app.model.Task = Task)。在第二種情況下,純粹主義者的觀點可能是它不太好。我寧願做類似window.app.collection.Tasks = Tasks的事情,然後定義一個靜態方法Tasks.getinstance(),它返回單例。或者,較不好的(但較少的編碼)將把你的單身人士放在全球範圍以及window.app.singletons.Tasks = Tasks()

最後,確保(因爲我相信你有),所有這些都是正確的範圍。此代碼(在瀏覽器中運行)還將創建任務和任務全局對象。總結這件事的功能,並使用var

(function (app) { 
    var Task = Backbone.Model.extend({ /*....*/ }), 
    Tasks = Backbone.Collection.extend({ /*....*/ }, { 
    getInstance: function() { 
     if (!this.instance) { 
     this.instance = new Tasks(); 
     } 
     return this.instance; 
    } 
    }); 

    if (!app.models) { 
    app.models = {}; 
    } 
    if (!app.collections) { 
    app.collections = {}; 
    } 

    app.models.Task = Task; 
    app.collections.Tasks = Tasks; 
}(window.app)); 
0

我個人不會污染全局命名空間是沿AMD解決方案的線路。這裏有一篇關於sharing resources across AMD modules的帖子,基本上你想要做什麼,但有一個模型和收藏。

此外,在Backbone Aura框架的issue的底部,還有一個數據模塊的實現,該模塊用於檢索命名空間集合和模型。我剛剛在我的應用程序中遇到了這個問題,這是我計劃實施的。