官术网_书友最值得收藏!

Region

A common use case is to swap between views in a common DOM element; this can be done by using the same el property in both views and calling the render() method on the view you want to see. But this way doesn't clean the memory and event bindings because both views will remain live in memory, even if they are not in the DOM.

A particularly useful scenario is when you need to switch between sub-applications, because sub-applications are rendered in the same DOM element normally. For example, when a user wants to edit contact information, he/she will click on an Edit button, and the current view will be replaced with an edit form.

Figure 2.2: Swapping views with regions

To switch between views, a Region class could be used as shown next:

var mainRegion = new Region({el: '#main'});
var contactViewer = new ContactViewer({model: contact});

contactViewer.on('edit:contact', function(contact) {
  var editContact = new EditContactView({ model: contact });
  mainRegion.show(editContact);
});

mainRegion.show(contactViewer);

The Region object points to an existing DOM element; to show a view on that element, the show() method should be called on the Region object. Note that views don't have the el property set because regions will put the element in the DOM and not the View itself. This gives us an extra feature, views don't need to set an el property anymore and can be rendered on any available region.

A basic region manager can be implemented with this code:

class Region {
  constructor(options) {
    this.el = options.el;
  }

  // Closes any active view and render a new one
  show(view) {
    this.closeView(this.currentView);
    this.currentView = view;
    this.openView(view);
  }

  closeView(view) {
    // Only remove the view when the remove function
    // is available
    if (view && view.remove) {
      view.remove();
    }
  }

  openView(view) {
    // Be sure that this.$el exists
    this.ensureEl();

    // Render the view on the this.$el element
    view.render();
    this.$el.html(view.el);
  }

  // Create the this.$el attribute if do not exists
  ensureEl() {
    if (this.$el) return;
    this.$el = $(this.el);
  }

  // Close the Region and any view on it
  remove() {
    this.closeView(this.currentView);
  }
}

When the show() method is called, it closes the current view, if any, then assigns a new currentView and opens the view. When a view is open, Region ensures that the $el property exists, first calling the ensureEl() method. Then the interesting part happens:

view.render();
this.$el.html(view.el);

The Backbone documentation explains how views works:

All views have a DOM element at all times (the el property), whether they've already been inserted into the page or not. In this fashion, views can be rendered at any time, and inserted into the DOM all at once [...]

And that's what happens here: we render the view in memory first, calling view.render(), and then insert the result in the DOM pointed by the Region $el property.

A remove() method is implemented too, to make regions compatible with Backbone Views. When a region is removed, it needs to close the owned view too, so this allows us to do this easily.

Imagine that we have a region that owns a CollectionView with many views inside; when the remove() method is called on the region, it will call the remove() method on the CollectionView, which will call the remove() method on every child view.

主站蜘蛛池模板: 隆回县| 双柏县| 临夏市| 施甸县| 漳平市| 文成县| 丰城市| 铁力市| 岳西县| 宁乡县| 启东市| 涿鹿县| 台安县| 大新县| 荣成市| 德昌县| 邓州市| 永宁县| 宜黄县| 邯郸市| 克什克腾旗| 泗水县| 丰原市| 杭州市| 灵武市| 元谋县| 石狮市| 牟定县| 乌鲁木齐市| 大埔区| 兴业县| 浦城县| 瑞丽市| 驻马店市| 商都县| 莱阳市| 改则县| 盘锦市| 丰台区| 乌鲁木齐县| 明光市|