Backbone/Require Application中共享对象的最佳实践

Bar*_*art 17 amd requirejs backbone.js

我一直在开发Backbone应用程序,我刚开始学习使用Backbone和Require.js.

在我重构的骨干应用程序中,我定义了一个这样的命名空间:App.model.repo.该模型在不同视图中反复使用.例如,我用一些集合做同样的事情App.collection.files.使用初始索引文件请求引导这些模型和集合.

我确实找到了这个示例,这看起来像是获取引导数据的好方法.但是,我正在努力寻找重用/共享这些模型和视图之间的集合的最佳方法.

我可以想到三种可能的解决方案.哪个最好,为什么?或者是否有我完全遗漏的另一种解决方案?

解决方案1

在索引中定义这些常用模块和集合(当它们被引导时),然后将它们作为选项(of initialize)传递给每个Backbone视图.

define(['jquery', 'underscore', 'backbone', 'handlebars', 'text!templates/NavBar.html'], 
    function($, _, Backbone, Handlebars, template){     
        return Backbone.View.extend({
            template: Handlebars.compile(template),
            initialize: function(options){
                this.repoModel = options.repoModel; // common model passed in
            }
        });
    }
);
Run Code Online (Sandbox Code Playgroud)

就分离来说,这些看起来很干净,但是可以快速得到时髦,大量的东西都会传遍整个地方.

解决方案2

定义globals模块,并向其中添加常用的模型和集合.

// models/Repo.js
define(['backbone'],
    function(Backbone){
        return Backbone.Model.extend({
            idAttribute: 'repo_id'
        });
    }
);

// globals.js (within index.php, for bootstrapping data)
define(['underscore', 'models/Repo'], 
    function(_, RepoModel){     
        var globals = {};

        globals.repoModel = new Repo(<?php echo json_encode($repo); ?>);

        return globals
    }
);

define(['jquery', 'underscore', 'backbone', 'handlebars', 'text!templates/NavBar.html', 'globals'], 
    function($, _, Backbone, Handlebars, template, globals){
        var repoModel = globals.repoModel; // repoModel from globals

        return Backbone.View.extend({
            template: Handlebars.compile(template),
            initialize: function(options){

            }
        });
    }
);
Run Code Online (Sandbox Code Playgroud)

这个解决方案是否打败了AMD的全部观点?

解决方案3

让一些模型和集合返回一个实例,而不是构造函数(有效地使它们成为单例).

// models/repo.js
define(['backbone'],
    function(Backbone){
        // return instance
        return new Backbone.Model.extend({
            idAttribute: 'repo_id'
        });
    }
);

// Included in index.php for bootstrapping data
require(['jquery', 'backbone', 'models/repo', 'routers/Application'],
    function($, Backbone, repoModel, ApplicationRouter){
        repoModel.set(<?php echo json_encode($repo); ?>);

        new ApplicationRouter({el: $('.site-container')});
        Backbone.history.start();
    }
);

define(['jquery', 'underscore', 'backbone', 'handlebars', 'text!templates/NavBar.html', 'models/repo'], 
    function($, _, Backbone, Handlebars, template, repoModel){
        // repoModel has values set by index.php

        return Backbone.View.extend({
            template: Handlebars.compile(template),
            initialize: function(options){

            }
        });
    }
);
Run Code Online (Sandbox Code Playgroud)

我担心这可能会让什么是构造函数以及什么是实例会让人感到困惑.

结束

如果你读到这里,你真棒!感谢您抽出宝贵的时间.

Sim*_*ias 4

就我而言,我更喜欢选项 3。不过,为了防止混淆,我将每个单例实例放在各自名为 的文件夹中instances。另外,我倾向于将模块model/collectioninstance模块分开。

然后,我就打电话给他们:

define([
  "instance/photos"
], function( photos ) { /* do stuff */ });
Run Code Online (Sandbox Code Playgroud)

我更喜欢这个选项,因为每个模块都被迫定义其依赖项(例如,通过命名空间不是这种情况)。解决方案 2 可以完成这项工作,但如果我使用 AMD,我希望我的模块尽可能小 - 而且保持它们很小可以更容易进行单元测试。

最后,关于单元测试,我可以在单元测试中重新定义实例以使用模拟数据。所以,毫无疑问,选择 3。

您可以在我正在处理 ATM 的开源应用程序上看到此模式的示例: https: //github.com/iplanwebsites/newtab-bookmarks/tree/master/app