Backbone View Inheritance

2020-03-19 04:00发布

问题:

I am trying to write a Backbone view for an object browser which is designed to be implemented in several places with different object types and slightly different operation. How can I achieve some good code reuse.

I have tried simply extending the backbone view in my browser and then extending the browser in my implementation however this leaves me with some properties which are shared. This is an undesired effect as the data is appended to all implementations with every browser creation.

Could someone shed light on a way to solve this problem or perhaps an alternative solution?

Here are some code examples to give you a better idea of how it currently stands:

    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({

    });

As always I more than welcome feedback in regards to any aspect of the code snippet I have provided.

Thank you, Alex

EDIT My issue is that the sub classes are sharing the collections property. Here is an example of my own solution which initialises the collections property through an inherited method. jsfiddle.net/JhZXh/3

回答1:

This gist shows a better alternative: https://gist.github.com/2287018



回答2:

I think I've figured out the answer to my own problem.

I believe the right way to achieve what I am looking for is to move the initialization of properties in to the initialize method provided by Backbone views. This way they are initialized

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);

Go here for a fiddle http://jsfiddle.net/yssAT/2/



回答3:

It's hard to see what exactly your goal is.

but this is how i see it if you have an view object

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

and you have it extend the backbone.View... then you actually have a new view object with everything of backbone.view, and the extra options you give as parameters.

if you then go and create a second view, that extends your first one it will get everything from your first view, + it's own extras

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

if you would create an instance of the second view and log it's foo property it will still hold "bar" as value

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

if i create a new instance of my first view, and change foo into "changed-foo" the log of foo on mySecondViewInstance will still be "bar"

var myViewInstance = new myView();
myViewInstance.foo = "changed-foo";
console.log("mySecondViewInstance.foo: ", mySecondViewInstance.foo);
console.log("mySecondViewInstance.foobar: ", mySecondViewInstance.foobar);

a JS-Fiddle to play around with it can be found here: http://jsfiddle.net/saelfaer/uNBSW/



回答4:

Inherit from Backbone.View doesn't work, or is quite complex.

You should create a common object, which every of your view will inherit from, ie :

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

each of your view would extend from this object :

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

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