【问题标题】:overriding Backbone.View delegateEvents so the events object can include mobile events覆盖 Backbone.View delegateEvents,以便事件对象可以包含移动事件
【发布时间】:2013-04-17 18:59:36
【问题描述】:

我正在使用 Hammer.js 在主干视图中捕获触摸屏事件。 Hammer 有一个特殊的语法来添加触摸监听器,我一直在 View 的初始化函数中使用它:

$("#next-button").hammer({prevent_default: true}).on('tap', $.proxy(this.next, this));

我宁愿将它添加到标准事件对象中,如下所示:

events: {"tap #next-button":"next"}

所以我破解了 Backbone.View 的 delegateEvents 方法的结尾:

var isMobileEvent=["tap", "doubleTap"].indexOf(eventName)!=-1;
        if (selector === '') {
            if (isMobileEvent){
                this.$el.hammer({prevent_default: true}).on(eventName, method);
            } else {
                this.$el.on(eventName, method);
            }
        } else {
            if (isMobileEvent){
                this.$el.hammer({prevent_default: true}).on(eventName, selector, method);
            } else {
                this.$el.on(eventName, selector, method);
            }

        }

这很好用。但是当我试图在需要覆盖的一个视图中覆盖该方法时(担心我会忘记 Backbone 中的这个 hack,或者用新版本的 Backbone 覆盖它等),我的视图的 delegateEvents 停止工作.问题是方法回调没有被识别为方法:

if (!_.isFunction(method)) method = this[events[key]];

为什么?我从字面上将函数复制并粘贴到 View 子类中。这是在 Backbone 中工作的整个 delegateEvents,但不在我的 Backbone.View 中:

delegateEvents: function(events) {
      if (!(events || (events = _.result(this, 'events')))) return;
      this.undelegateEvents();
      for (var key in events) {
        var method = events[key];
        if (!_.isFunction(method)) method = this[events[key]];
        if (!method) throw new Error('Method "' + events[key] + '" does not exist');
        var match = key.match(delegateEventSplitter);
        var eventName = match[1], selector = match[2];
        method = _.bind(method, this);
        eventName += '.delegateEvents' + this.cid;
        var isMobileEvent=["tap", "doubleTap"].indexOf(eventName)!=-1;
        if (selector === '') {
            if (isMobileEvent){
                this.$el.hammer({prevent_default: true}).on(eventName, method);
            } else {
                this.$el.on(eventName, method);
            }
        } else {
            if (isMobileEvent){
                this.$el.hammer({prevent_default: true}).on(eventName, selector, method);
            } else {
                this.$el.on(eventName, selector, method);
            }

        }
      }

修复:

替换这一行:

var match = key.match(delegateEventSplitter);

用这个:

var match = key.match(/^(\S+)\s*(.*)$/);

【问题讨论】:

  • 你是如何覆盖它的?
  • 你的View 类中有next 函数/方法吗?
  • @Loamhoof 我只是在 View 子类中添加了一个 delegateEvents 方法。我也从未重写过 js 函数或 Backbone 函数。这足够了吗?其他 StackOverflow 帖子中的代码似乎遵循这种模式。
  • 你在哪里声明delegateEventSplitter?我将delegateEvents 代码复制到此处的子类 View 中,并且在我复制了该变量的值之后它起作用了。 jsbin.com/iqibur/1/edit
  • "JS 让我很困惑。" => 这就是我喜欢它的原因 ;) 首先,如果在 Backbone.View 中将 delegateEventSplitter 声明为 var delegateEventSplitter = /^(\S+)\s*(.*)$/; 它不会更改任何内容,这将是一个私有 var,并且只有构造函数和构造函数中声明的方法(而不是原型方法)才能访问它,范围问题。现在关于范围,基本上您将永远无法访问 Backbone 的范围,因为您需要在范围内定义事物才能访问它:)

标签: javascript backbone.js hammer.js


【解决方案1】:

这个jsbin 展示了如何覆盖delegateEvents 的默认主干View 逻辑。

您可以根据需要轻松扩展它来处理 Hammer.JS,就像上面扩展 Backbone 以支持各种触摸事件一样。

我需要在本地复制 delegateEventSplitter 的值,因为它是在 Backbone 库中私下声明的(在闭包内)。只有在该变量的上下文中执行/返回的函数才能访问该值。由于您的新类不在该上下文中执行,因此无法直接访问该值。

相关代码:

var SampleView = Backbone.View.extend({
  events: {
    "click" : '_clicked' 
  },

delegateEvents: function(events) {
      if (!(events || (events = _.result(this, 'events')))) return;
      this.undelegateEvents();
      for (var key in events) {
        var method = events[key];
        if (!_.isFunction(method)) method = this[events[key]];
        if (!method) throw new Error('Method "' + events[key] + '" does not exist');
        var match = key.match(/^(\S+)\s*(.*)$/);
        var eventName = match[1], selector = match[2];
        method = _.bind(method, this);
        eventName += '.delegateEvents' + this.cid;
        if (selector === '') {
           this.$el.on(eventName, method);
        } else {
           this.$el.on(eventName, selector, method);
        }
      }  
},

  render: function() {        
     this.$el.html("hi");
     return this; 
  },        
  _clicked: function() {
     alert("clicked!"); 
  }
});

// assumes there's an element with an id of "content"
$(function() {
  var view = new SampleView();
  $("#content").append(view.render().$el);  
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-02
    • 2011-10-10
    • 1970-01-01
    • 2014-07-12
    相关资源
    最近更新 更多