2

我最近遇到了Backbone和Require JS的問題,因爲我們有一個相當複雜的數據模型,我需要表示導致循環依賴的問題,自我引用。我在網上閱讀了大量的帖子(其中沒有一篇真的有效),但我認爲我找到了一個解決方案。因此,我希望能夠分享這一點,希望它能幫助遇到此問題的人,同時也問問你們是否認爲有辦法整理事情。骨幹js +需要js +骨幹關係+循環依賴+自引用

第一個問題是我的模型引用了引用集合的引用模型的集合,所有這些引用創建了一個大的凌亂的循環依賴關係。這坦率地打破了申請。下面是一個僞代碼示例:

Model A 
    has Collection B 

Collection B 
    of Model B 

Model B 
    has Collection A 
    has Collection C 

Collection A 
    of Model A 

Collection C 
    of Model C 

的骨幹docs狀態,這是可以做喜歡的事:

initialize: function() { 
    this.messages = new Messages; 
    this.messages.url = '/mailbox/' + this.id + '/messages'; 
    this.messages.on("reset", this.updateCounts); 
    }, 

我試圖解決這個對我們的需求,但我們複雜的嵌套要求的各種方式打破骨幹的地獄。所以我偶然發現了backbone relational,並創建了我們的數據模型的基本工作表示(這涉及創建一個墊片以處理需要JS)。本質上這工作。因此,我擴展了示例,以便模型C也可以具有Collection C(自引用)的實例。再次,這似乎工作。優秀。然而,將該示例應用到我的應用程序中更加困難 - 將模型和集合分割成單個文件證明更加困難,因爲骨幹關係期望集合和模型名稱位於全局名稱空間中(對於要求和「使用嚴格」有點棘手) 。由於我們複雜的數據模型,我想使用字符串標識符來表示關係,而不是明確的需要引用,這也很困難。我試着將所有東西都添加到出口命名空間,但是這再次無效。無論如何,我想我已經找到了一個解決方案,將集合和模型添加到自定義名稱空間,然後將此名稱空間添加到主幹關係模型範圍。我已經命名了我的自定義庫「Orca」(導致殺人鯨坦然地真棒)。

bootstrap.js

require.config({ 
    paths: { 
    "jquery"  : "../bower_components/jquery/jquery", 
    "underscore" : "../bower_components/underscore-amd/underscore", 
    "backbone"  : "../bower_components/backbone-amd/backbone", 
    "relational" : "../bower_components/backbone-relational/backbone-relational", 
    ... 

    shim: { 
    "underscore": { 
     exports: "_" 
    }, 
    "backbone": { 
     deps: ["underscore", "jquery"], 
     exports: "Backbone" 
    }, 
    "relational": { 
     deps: ["backbone"] 
    }, 
    ... 

app.js

define(["backbone", "relational", "libs/orca", "collections/a", "models/a", "collections/b", "models/b", "collections/c", "models/c"], function(Backbone, Relational, Orca){ 
    "use strict"; 

    var App = function(options) { 
    this.initialize(otions); 
    }; 

    App.prototype = _.extend(Backbone.Events, { 

    initialize: function(options) { 
     Orca.initialize(); 

     var a = new Orca.Relational.ModelA([],{}); 
    } 
    } 

    return App; 
}); 

LIB/orca.js

define(["backbone", "relational"], function(Backbone) { 
    "use strict"; 

    var Orca = { 
    Relational: {}, 

    initialize: function() { 
     Backbone.Relational.store.addModelScope(this.Relational);  
    } 
    }; 

    // I actually extend Backbone.RelationalModel so I can have custom methods, 
    // e.g. "parse" but I've simplified the code for example's sake... 
    Orca.Model = Backbone.RelationalModel; 
    Orca.Collection = Backbone.Collection; 

    return Orca; 
}); 

集合/ a.js

define(["backbone", "libs/orca"], function(Backbone, Orca) { 
    "use strict"; 

    Orca.Relational.CollectionA = Backbone.Collection.extend({}); 
}); 

型號/ a.js

define(["backbone", "libs/orca"], function(Backbone, Orca) { 
    "use strict"; 

    Orca.Relational.ModelA = Orca.Model.extend({ 
    relations: [ 
     { 
     type: Backbone.HasMany, 
     key: "bs", 
     relatedModel: "ModelB", 
     includeInJSON: Backbone.Model.prototype.idAttribute, 
     collectionType: "CollectionB", 
     reverseRelation: { 
      key: "a" 
     } 
     } 
    ] 
    }); 
}); 

CollectionB和ModelB是相似的,所以我省略了這些贅述。

爲了證明自我指涉:

define(["backbone", "libs/orca"], function(Backbone, Orca) { 
    "use strict"; 

    Orca.Relational.ModelC = Orca.Model.extend({ 
    relations: [ 
     { 
     type: Backbone.HasMany, 
     key: "cs", 
     relatedModel: "ModelC", 
     includeInJSON: Backbone.Model.prototype.idAttribute, 
     collectionType: "CollectionC", 
     reverseRelation: { 
      key: "c" 
     } 
     } 
    ] 
    }); 
}); 

所以我的這個代碼錯誤熊,在app.js創建MODELA的新實例。但是,因爲這引用了CollectionB,後者又由ModelB使用,ModelB反過來引用Collection C並使用Model C,那麼我必須將所有這些引用爲需求依賴關係。有一個更好的方法嗎?

+0

也許加入收藏和模型的「窗口」對象可能否定需要一個自定義對象,但我喜歡將事情從全局對象中排除出去的想法 –

回答

0

你有沒有提到Backbone Associations。我建議你一次看看它。

當我使用它時,我遇到了類似的循環依賴和自引用問題。原因是我將客戶端的Models映射到後端的Beans,後者使用Hibernate映射到Tables。當您在Hibernate中指定one-to-many關係時,您需要指定一個實體引用其他實體,反之亦然。然後,當Jersey服務返回這些實體時,轉換爲JSON具有循環依賴關係。我可以在後端使用some annotations擺脫它。但是在Backbone方面沒有辦法解決它。我與Backbone Associations的作者提出了這個問題,他們修正了它。

希望這有助於某些方面或其他方面。

+0

感謝您的評論並提出了其他庫 –

1

我實際上停止使用Backbone Relational,現在我使用JJRelational,因爲它允許多對多的關係。我也否定了通過創建一個名爲「relational.js」的新文件引用集合和模型並將它們作爲對象的屬性返回來引用集合和模型的需求。這樣我只需要「relational.js」,如果我需要一個新的模型或集合。

我relational.js文件看起來有點像這樣:

define([ 
    // Models 
    "models/broadcast", 
    "models/version", 
    // Collections 
    "collections/broadcasts", 
    "collections/versions" 

], function(
    // Models 
    Broadcast, 
    Version, 
    // Collections 
    Broadcasts, 
    Versions 
) { 
    "use strict"; 

    var _relational = { 
    Broadcast: Broadcast, 
    Version: Version, 

    Broadcasts: Broadcasts, 
    Versions: Versions, 
    }; 

    // Register the Collections 
    Backbone.JJRelational.registerCollectionTypes({ 
    "Broadcasts": _relational.Broadcasts, 
    "Versions": _relational.Versions  
    }); 

    // Provide JJRelational with model scope - pull request submitted to JJRelational to handle this 
    Backbone.JJStore.addModelScope(_relational); 

    return _relational; 
}); 

然後在我的主要app.js:

define(["libs/relational"], function(Relational){ 
    var broadcast = new Relational.Broadcast(); 
});