骨干视图继承

时间:2012-02-23 01:24:03

标签: javascript class view backbone.js prototype

我正在尝试为对象浏览器编写一个Backbone视图,该对象浏览器旨在在具有不同对象类型和略微不同操作的多个位置实现。我怎样才能实现一些好的代码重用。

我尝试过简单地在我的浏览器中扩展骨干视图,然后在我的实现中扩展浏览器,但是这给我留下了一些共享的属性。这是一种不受欢迎的影响,因为每次浏览器创建都会将数据附加到所有实现中。

有人可以解决一个解决这个问题的方法,或者可能是另一种解决方案吗?

以下是一些代码示例,可让您更好地了解目前的情况:

    var BrowserView = Backbone.View;

    _.extend(BrowserView.prototype, Backbone.View.prototype, {
        className: 'browser',

        collections: [],

        events: {

        },

        _events:{

        },

            initialize: function () {
            this._initialize();
        },

        render: function () {
            this._render();
        },

        _initialize: function () {
            this.container = $( this.make('div', {class: 'container'} ) );

            this.$el.append(this.container);

            if ( this.options.collections ) {
                this.collections = [];

                _.each(this.options.collections, this.add, this);
            }

            _.extend(this.events, this._events);

            this.delegateEvents();
        },

        _render: function () {
            this.container.empty();

            _.each(this.collections, function (view) {
                this.container.append(view.el);

                view.render();
            }, this);
        }
    });

    BrowserView.extend = Backbone.View.extend;

    var ContactBrowserView = BrowserView.extend({

    });

与往常一样,我非常欢迎您提供有关我提供的代码段的任何方面的反馈。

谢谢你, 亚历

修改 我的问题是子类共享集合属性。这是我自己的解决方案的一个示例,它通过继承的方法初始化collections属性。 jsfiddle.net/JhZXh/3

4 个答案:

答案 0 :(得分:11)

我想我已经找到了自己问题的答案。

我认为实现我正在寻找的正确方法是将属性的初始化移动到Backbone视图提供的initialize方法。这样就初始化了

var BrowserView = Backbone.View.extend({
    initialize: function () {
        this.collections = [];
    }
});

var FileBrowserView = BrowserView.extend({
    initialize: function () {
        BrowserView.prototype.initialize.apply(this);

        this.collections.push({name: 'Example Collection' + Math.rand()});
    }
});


var FileBrowserInstance1 = new FileBrowserView;
console.log(FileBrowserInstance1.collections);

var FileBrowserInstance2 = new FileBrowserView;
console.log(FileBrowserInstance2.collections);

去这里找个小提琴 http://jsfiddle.net/yssAT/2/

答案 1 :(得分:4)

很难看出你的目标是什么。

但这就是我的看法 如果你有一个视图对象

var myView = Backbone.View.extend({
    foo: "bar"
});

并且你扩展了主干。查看...然后你实际上有一个新的视图对象,包含backbone.view的所有内容,以及你作为参数提供的额外选项。

如果您再创建第二个视图,则会扩展您的第一个视图 它会从你的第一个视图中获得所有内容,+它自己的附加内容

var mySecondView = myView.extend({
    foobar: "f00b@r"
});

如果您要创建第二个视图的实例并将其记录为foo属性,它仍会保留"bar"作为值

var mySecondViewInstance = new mySecondView();
console.log("mySecondViewInstance.foo: ", mySecondViewInstance.foo);
console.log("mySecondViewInstance.foobar: ", mySecondViewInstance.foobar);

如果我创建了第一个视图的新实例,并将foo更改为"changed-foo" foomySecondViewInstance的日志仍为"bar"

var myViewInstance = new myView();
myViewInstance.foo = "changed-foo";
console.log("mySecondViewInstance.foo: ", mySecondViewInstance.foo);
console.log("mySecondViewInstance.foobar: ", mySecondViewInstance.foobar);
可以在这里找到一个JS-Fiddle来玩它: http://jsfiddle.net/saelfaer/uNBSW/

答案 2 :(得分:3)

继承Backbone.View不起作用,或者非常复杂。

您应该创建一个公共对象,您的每个视图都将继承该公共对象,即:

var ViewInterface = {
  events        : { /* ... */ },
  initialize    : function (options) { /* ... */ },
  otherFunction : function (options) { /* ... */ },
}

您的每个视图都会从此对象扩展:

var BrowserView = Backbone.View.extend(_.extend(ViewInterface, {
  anotherFunction : function (options) { /* ... */ },
})

var AnotherView = Backbone.View.extend(_.extend(ViewInterface, {
  yetAnotherFunction : function (options) { /* ... */ },
})

答案 3 :(得分:2)

这个要点显示了一个更好的选择: https://gist.github.com/2287018