2011-06-12 18 views
10

Estoy intentando reescribir una clase de información sobre herramientas de Mootools en JQuery usando este class plugin. Cuando se crea una instancia de mi clase, adjunto un detector de eventos a un enlace de destino que desvanecerá la información sobre herramientas.JQuery equivalente de MooTools bind (this)

En devoluciones de llamadas de eventos JQuery asigna la palabra clave "this" al destino del evento, así que para mantener una referencia a las propiedades de la clase estoy usando apply() para establecer "this" para indicar la instancia de clase. Aparentemente, esta es la contraparte en la función bind() handy de JQuery of Mootools.

Desafortunadamente cuando uso apply() pierdo el parámetro de evento de devolución de llamada. Por ejemplo, en este bit aparece el error "e no está definido" en la segunda línea.

this.target.bind('click', function(e){ 
    e.preventDefault(); 
    var tip = this.opts.tip; 
    tip.fadeOut(500, function(){ 
     tip.bind('click', function(){ 
      showing = false; 
     }) 
    }); 
}.apply(this)) 

¿Falta algún truco aquí? ¿Alguien sabe una forma de evitar este problema?

Gracias Fred

Respuesta

18

TBH, mootools.bind como lo llamaste es solo Function.bind en ES5, y está disponible de forma nativa en navegadores compatibles con la especificación js 1.8.5 +. MooTools solo mejora los navegadores que aún no lo tienen, pero permite que la implementación nativa permanezca en el prototipo, si está disponible.

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

Se puede implementar fácilmente que a modo de un Function.prototype.bind decorador si no está disponible de forma nativa y utilizarlo como el ejemplo anterior dice:

// Function.prototype.bind polyfill 
if (!Function.prototype.bind) { 

    Function.prototype.bind = function(obj) { 
    if(typeof this !== 'function') // closest thing possible to the ECMAScript 5 internal IsCallable function 
     throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 

    var slice = [].slice, 
     args = slice.call(arguments, 1), 
     self = this, 
     nop = function() {}, 
     bound = function() { 
      return self.apply(this instanceof nop ? this : (obj || {}), 
           args.concat(slice.call(arguments)));  
     }; 

    bound.prototype = this.prototype; 

    return bound; 
    }; 
} 

Como se puede ver, que es un poco más complicado que una simple .apply/.call

Una cosa a considerar es, si NECESITA utilizar bind o si puede guardar una referencia en su lugar.

por ejemplo.

var self = this; 
this.target.bind("click", function(e) { 
    var tip = self.opts.tip; 
}); 

esto tiene una huella más pequeña que la función de enlace de todos modos. también le proporciona una referencia correcta de this como elemento desencadenante (event.target === this). se encuentra este patrón mucho más a menudo en mootools-core que la unen uno - aunque se unen con frecuencia es necesaria cuando se desea asignar eventos a los métodos de clase, por ejemplo:

this.element.addEvents({ 
    click: this.showTip.bind(this), 
    mouseleave: this.hideTip.bind(this) 
}); 

En este caso, el ahorro de una referencia ganó' t trabajo, aunque se puede reescribir como

var self = this; 
this.element.addEvents({ 
    click: function(e) { 
     self.showTip(e); 
    } 
}); 

Un jQuery implementación particular es proxy - mkilmanas http://api.jquery.com/jquery.proxy/

+0

Dimitar ¡eres una enciclopedia andante de JS! Gracias por la explicación detallada.En esta situación, su sugerencia de una referencia parece ser la mejor, así que me gustaría hacer: '\t var self = this; \t this.target.bind ('clic', la función (e) { \t \t e.preventDefault(); \t \t self.toggleTip(); \t}) ' en mi método init, donde toggleTip () es una devolución de llamada por clic separada. ¡Un gran consejo, gracias! –

+0

@Dimitar: funciona muy bien. thnx. (at) all: Note que esta técnica de programación funcional se llama currying (http://www.dustindiaz.com/javascript-curry/). jQuery tiene una extensión de prototipo similar del nombre del método 'bind', que puede ser algo confuso porque se usa para el manejo de eventos y se declara para las no funciones. En jQuery también hay un uso del contexto en $ .ajax para un propósito similar. –

0

Todos los eventos, que se realizan en algún elemento (por ejemplo, 'clic' es uno de ellos) debe tener una propiedad de destino que apunta a ese elemento

var $this = $(e.target); // $this will be the clicked element 

JSFiddle

+0

, gracias - que es la propiedad que estaba esperando para usar. Lamentablemente, cuando agregué apply() al final de mi función, perdí el acceso. –