Backbone + RequireJS:使收藏持续存在?

时间:2012-08-31 15:58:07

标签: javascript backbone.js requirejs

我正在使用Backbone和RequireJS,我的View需要在相应的RESTful API之类的20个集合之间切换。

“正常”方式可以很好地处理事情,除了每个API都需要定义一个新的Collection,导致代码库变得非常膨胀:

收藏(x 20次)

define(function(require) {
    var Backbone = require('backbone');

    var c = Backbone.Collection.extend({
        url: '/path/to/api-1'
    });

    return new c();
});

查看

define(function(require) {
    var Backbone = require('backbone'),
           c1 = require('./collections/collection-1'),
           ...
           c20 = require('./collections/collection-20');

    var v = Backbone.View.extend({
        /* Some methods to toggle between Collections here */
    });

    return v;
});

只在集合中执行return c;,并在View中调用new c({url: /path/to/api-1});,我就能够减少高度重复的集合定义;但是现在每次new c();次调用时,都会调用API来检索新的数据副本,这对资源和我不想要的东西都是浪费。

有没有办法让收藏品“持久”?哪个更符合以下所有标准:

  • 对于每个API的相应Collection,只执行一个new;
  • 可以使用RequireJS;
  • 定义的不同视图共享/访问每个集合
  • 所有API都可以重用Collection的定义;
  • 全局命名空间根本没有受到污染。

3 个答案:

答案 0 :(得分:0)

您无需制作新文件/集合。

您可以在视图中执行以下操作:

var collections = [];
collections.push( Backbone.Collection.extend({url: '/path/to/api-1'});
collections.push( Backbone.Collection.extend({url: '/path/to/api-2'});
collections.push( Backbone.Collection.extend({url: '/path/to/api-3'});

...

collections.push( Backbone.Collection.extend({url: '/path/to/api-20'});

var view1 = Backbone.View.extend( {data:collections} );
var view2 = Backbone.View.extend( {data:collections} );

然后,您将拥有一个装有所有集合的数组

答案 1 :(得分:0)

与另一个答案类似,您可以将集合数组定义为AMD模块:

<强>集合

define(['backbone', 'underscore'], function(Backbone, _) {
    var collections = [];

    var urls = ['/path/to/api-1', '/path/to/api-2', '/path/to/api-3'];

    _(urls).each(function(url) {
        collections.push(Backbone.Collection.extend({
            url: url
        }));
    });

    return collections;
});

您的观点可以像这样使用:

查看

define(['Backbone', 'collections'], function(Backbone, collections) {

    var v = Backbone.View.extend({
        /* Some methods to toggle between Collections here */
    });

    return v;
});

答案 2 :(得分:0)

找到一个相当狡猾的解决方案:

使用其他模型

包裹您的集合
define(function(require) {
    var Backbone = require('backbone'),
        m = require('../models/model');

    var wrapper = Backbone.Model.extend({
        initialize: function() {
            var $_path = this.get('path');

            var c = Backbone.Collection.extend({
                model: m,

                url: $_path,

                initialize: function() {
                    this.deferred = this.fetch();
                }
            });

            this.set({
                collection: new c()
            });
        }
    });

    return wrapper;
});

然后,定义一个Cache容器:

define(function(require) {
    return cache = {};
});

在View模块中同时需要Cache容器和包装的Collection:

define(function(require) {
    var $ = require('jquery'),
        _ = require('underscore'),
        Backbone = require('backbone'),
        cache = require(cache),
        wrapper = require('../collections/collection');

    var v = Backbone.View.extend({
        render: function($_path) {
            var c = cache[$_path] || cache[$_path] = new wrapper({
                path: $_path
            }).get('collection'));
        } 
        ....
    });

    return v;
});

通过这种方式,您既可以获得使用动态生成的$_path值实例化新集合的好处,又可以在不刷新页面的情况下缓存从API获取的数据 - 实现localStorage你希望数据在页面刷新时保持不变。