覆盖Backbone.View delegateEvents这样的事件对象可以包括移动事件 [英] overriding Backbone.View delegateEvents so the events object can include mobile events

查看:791
本文介绍了覆盖Backbone.View delegateEvents这样的事件对象可以包括移动事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Hammer.js捕捉中的骨干视图触摸屏事件。锤有一个特殊的语法加触摸的听众,我一直在使用视图的初始化函数其中:

  $(#下按钮),锤({prevent_default:真})。在('水龙头',$ .proxy(this.next,这一点) );

我宁愿把它添加到标准事件对象,像这样的:

 事件:{自来水#下按钮:下一步}

所以我砍死Backbone.View的delegateEvents方法的末尾:

  VAR isMobileEvent = [龙头,doubleTap]的indexOf(eventName的)=  -  1。!;
        如果(选择===''){
            如果(isMobileEvent){
                这$ el.hammer({prevent_default:真})。在(eventName的,法);
            }其他{
                这$ el.on(eventName的,方法)。
            }
        }其他{
            如果(isMobileEvent){
                这$ el.hammer({prevent_default:真})。在(eventName的,选择器,法);
            }其他{
                这$ el.on(eventName的,选择器,方法)。
            }        }

这工作正常。但是,当我试图重写方法之一查看它被需要的倍率(担心我会忘记这个技巧的骨干,或骨干的新版本等覆盖它),我查看delegateEvents停止工作。问题是,该方法回调不被识别为一个方法:

 如果(!_ isFunction(法))方法=本[赛事[关键]];

为什么呢?我从字面上复制并粘贴功能到视图子类。这里是整个delegateEvents在骨干工作,但不是在我Backbone.View:

  delegateEvents:函数(事件){
      如果收益率((事件||(事件= _.result(这一点,事件)))!);
      this.undelegateEvents();
      对(在事件VAR键){
        VaR方法=事件[关键]
        如果(!_ isFunction(法))方法=本[赛事[关键]];
        如果(!方法)抛出新的错误('法'+事件[键] +'不存在');
        VAR匹配= key.match(delegateEventSplitter);
        VAR eventName的比赛= [1],选择=匹配[2];
        方法= _.bind(方法,这一点);
        eventName的+ ='.delegateEvents'+ this.cid;
        VAR isMobileEvent =点击,doubleTap]的indexOf(eventName的)= - 1。!;
        如果(选择===''){
            如果(isMobileEvent){
                这$ el.hammer({prevent_default:真})。在(eventName的,法);
            }其他{
                这$ el.on(eventName的,方法)。
            }
        }其他{
            如果(isMobileEvent){
                这$ el.hammer({prevent_default:真})。在(eventName的,选择器,法);
            }其他{
                这$ el.on(eventName的,选择器,方法)。
            }        }
      }

解决方法:

替换此行:

  VAR匹配= key.match(delegateEventSplitter);

这一个:

  VAR匹配= key.match(/ ^(\\ S +)\\ S *(*)$ /);


解决方案

jsbin 展示了如何它可以覆盖默认的骨干查看逻辑 delegateEvents

根据需要,你上面不得不延长骨干,以支持各种触摸事件处理Hammer.JS您可以轻松地将其扩展。

我需要复制 delegateEventSplitter 的价值在本地,因为它的骨干图书馆内声明为私有(闭包内)。该变量的范围内返回已执行的功能只/能够访问该值。因为你的新类没有在这方面执行的,这是无法直接访问的值。

相关code:

  VAR SampleView = Backbone.View.extend({
  事件:{
    点击:_clicked
  },delegateEvents:函数(事件){
      如果收益率((事件||(事件= _.result(这一点,事件)))!);
      this.undelegateEvents();
      对(在事件VAR键){
        VaR方法=事件[关键]
        如果(!_ isFunction(法))方法=本[赛事[关键]];
        如果(!方法)抛出新的错误('法'+事件[键] +'不存在');
        VAR匹配= key.match(/ ^(\\ S +)\\ S *(*)$ /);
        VAR eventName的比赛= [1],选择=匹配[2];
        方法= _.bind(方法,这一点);
        eventName的+ ='.delegateEvents'+ this.cid;
        如果(选择===''){
           这$ el.on(eventName的,方法)。
        }其他{
           这$ el.on(eventName的,选择器,方法)。
        }
      }
},  渲染:功能(){
     这$ el.html(HI);
     返回此;
  },
  _clicked:功能(){
     警报(点击!);
  }
});//假设有一个元素与内容的ID
$(函数(){
  VAR视图=新SampleView();
  $(#内容),追加(view.render()$ EL);
});

I am using Hammer.js to capture touchscreen events in a Backbone View. Hammer has a special syntax for adding touch listeners, which I have been using in the View's initialize function:

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

I would rather add it to the standard events object, like this:

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

So I hacked the end of Backbone.View's delegateEvents method:

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

        }

This works fine. But when I tried to override the method in the one View where it was needed the override (worried that I would forget about this hack in Backbone, or overwrite it with a new version of Backbone, etc.), delegateEvents for my View stopped working. The problem is that the method callback is not recognized as a method:

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

Why? I literally copy and pasted the function into the View subclass. Here is the whole delegateEvents that works in Backbone, but not in my 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);
            }

        }
      }

THE FIX:

Replace this line:

var match = key.match(delegateEventSplitter);

with this one:

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

解决方案

This jsbin shows how it is possible to override the default Backbone View logic for delegateEvents.

You can easily extend it as needed to handle Hammer.JS as you had above to extend Backbone to support the various touch events.

I needed to copy the value of delegateEventSplitter locally as it's privately declared (within a closure) inside of the Backbone library. Only functions that were executed/returned within the context of that variable are able to access that value. Since your new class does not execute in that context, it's unable to directly access the value.

The relevant code:

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

这篇关于覆盖Backbone.View delegateEvents这样的事件对象可以包括移动事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆