Nesting Views within Views in backbone js

2020-08-13 06:34发布

问题:

I'm working with backbone.js building some complex view relationships, and I'm wondering if there are any problems from a javascript performance standpoint of doing something that looks like this:

var viewOne = Backbone.View.extend({
         tagName : 'li',
         initialize : function() {
              this.v2 = new viewTwo({parent:this});
         },
         clickHideOne : function() {
              $(this.el).removeClass('selected');
         }
});

var viewTwo = Backbone.View.extend({
         tagName : 'a',
         initialize : function() {
              this.bind('click', this.clickHide, this);
         },
         clickHide(){
              $(this.el).removeClass('selected');
              this.options.parent.clickHideOne();
         }
});

Where this is a very simple example of a circular reference between two views, in order to have events in one view easily propagate up a chain of views, or maintain any references to objects in the parent views. Are there any situations where this would be a problem, specifically in relation to the potential leaks with DOM element references in IE7+, or is there another recommended best practice for referencing parent views.

Also, I understand that I could just do $(this.el).parent('li').removeClass('selected'); in viewTwo, that's not the point... this just a very simple example of the question I have about the circular reference.

回答1:

Having a parent view responsible for child views is not a bad idea and is quite a common scenario in backbone. The problem I see with the code above is the fact that the child view has knowledge of its parent view. I would suggest using custom events in the viewTwo and have viewOne bind to those events and then respond accordingly.

This is quite easy with backbone by using the trigger() method and the bind() method.



回答2:

Circular references are a bad idea. It is also not good practice, as Kyle said, that a child view have an explicit reference to its parent view. Explicit references should go DOWN the view hierarchy only. That is, it is fine, and typical, for a parent view to have explicit references to all its child views, and to call methods of child views to interact with them. (See Backbone.Subviews mixin for each way to create and manage child views). However, best encapsulation practice dictates a view should never have explicit references or directly call directly methods of its siblings or its parents.

In order to communicate with siblings or parents, you have three options that I am aware of:

  1. Use view.trigger() to trigger an event on the child view (or sibling), and then have the parent (or sibling) listen to that event using view.listenTo(). This approach works but starts to break down when you want a child view to communicate with its grandfather, etc. Also, you create unneeded explicit dependencies if you use this approach with siblings.

  2. You can use Backbone.Courier, which is a plugin that makes it easy to bubbling up events in the view hierarchy. For communication between sibling views, one sibling bubbles an event up to the parent, and then the parent calls a method of the other sibling directly.

  3. You can use an event aggregator to act as an intermediate object between child and parent, or between siblings. That way these views can communicate through the aggregator, without explicit references to each other. However, this approach requires global aggregator objects, and also allows a criss-crossing of implicit dependencies, which can become difficult to manage as the number of views grows.



回答3:

Nesting is a good way of maintaining hierarchical views for writing maintainable code for complex user interfaces. In the simple example there are hardly any performance issues but in more complex situations you do need to keep in mind how deep your nesting goes. For example using complex cell-renderers improperly in a grid of thousands of rows might render your application unusable. In such cases clever optimizations can usually be made eg. using renderers for only the visible grid cells.