如何在每个Marionette视图渲染上记录消息?

时间:2014-05-17 08:59:51

标签: javascript backbone.js marionette

我有一个带有大量视图的Marionette应用程序。我想在每个渲染时将调试消息记录到控制台(并且可能在将来,在其他事件上)

我目前通过从每个View的onRender方法记录来执行此操作:

MyModule.MyViewType = Marionette.ItemView.extend({
    // ... view properties and methods

    onRender: function() {
      // ... other onRender code
      console.debug('MyModule.MyViewType %s %s', this.cid, 'render');
    }
});

这有效,但它有几个缺点:

  • 必须手动将日志记录代码添加到每个视图。
  • 多个视图没有自定义onRender操作,所以我只是为了调试而添加方法。那感觉不对。
  • 如果我想完全改变或删除日志记录方法(例如去生产),我需要改变很多代码。
  • 如果我想为其他活动添加代码,例如show,我需要为每个视图添加一个事件处理程序或一个新方法。

有没有办法记录每个视图渲染而不向每个视图添加代码?

1 个答案:

答案 0 :(得分:5)

是。您可以decorate Backbone.View.constructor加入View创建生命周期。然后,您可以为所有View实例上的任何事件注册回调。

!function() {
  // Development: log view renders and other events
  // Don't execute this function in production.


  // Save a reference to the original Backbone.View and create a new type
  // that replaces the constructor method
  var OriginalView = Backbone.View,
      LoggingView = OriginalView.extend({
        constructor: function() {

          // Execute the original constructor first
          OriginalView.apply(this, arguments);

          // Allow views to define a `type` property to clarify log messages
          var type = this.type || 'Unknown View Type',
              cid = this.cid;

          // Bind to Marionette.View's `render` event (and any other events)
          this.listenTo(this, 'render', function(e,b) {
            console.debug('%s %s - %s', type, cid, 'render');
          });
        }
      });

  // Replace Backbone.View with our decorated view
  Backbone.View = LoggingView;
}();

要记录视图类型,请在View实现中添加属性:

MyModule.MyViewType = Marionette.ItemView.extend({
    type: 'MyModule.MyViewType',
    // ... rest of the view code
});

可靠地确定JavaScript的对象“type”(构造函数名称)是problematic,因此添加此属性是确定正在呈现的视图类型的最佳方法。

通过提供您要记录的事件数组,可以很容易地将此​​答案推广到多个事件类型:

var events = ['render', 'show', 'beforeClose'];

events.forEach(function(eventType) {
  this.listenTo(this, eventType, function() {
    console.debug('%s %s - %s', type, cid, eventType)
  });
}).bind(this);

示例输出:

Projects.ViewType1 view13 - render 
Projects.ViewType2 view3 - render 
Projects.ViewType3 view6 - render 
Projects.ViewType4 view9 - render 
Projects.ViewType4 view17 - render
Projects.ViewType4 view19 - render 
Projects.ViewType2 view3 - render

这种方法解决了问题中描述的所有问题 - 代码量很少,视图不需要直接修改,只有一个函数调用可以省略,以删除生产代码中的日志记录。

这种方法特定于Marionette - 因为vanilla Backbone的render方法是用户定义的,没有等同于render事件。

有关扩展Backbone构造函数方法的更多详细信息,请参阅Derick Bailey's blog