JQuery-эквивалент MooTools bind (это) - PullRequest
11 голосов
/ 12 июня 2011

Я пытаюсь переписать класс всплывающей подсказки Mootools в JQuery, используя этот плагин класса . Когда создается мой класс, я присоединяю прослушиватель событий к целевой ссылке, которая исчезает во всплывающей подсказке.

В обратных вызовах событий JQuery назначает ключевое слово "this" для цели события, чтобы сохранить ссылку на свойства класса, который я использую apply (), чтобы установить "this" для обозначения экземпляра класса. Это, очевидно, аналог в удобной функции Mindoools bind () в JQuery.

К сожалению, когда я использую apply (), я теряю параметр события обратного вызова. Например, в этом бите я получаю ошибку «e is undefined» во второй строке.

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

Мне не хватает трюка здесь? Кто-нибудь знает способ обойти эту проблему?

Спасибо Фред

Ответы [ 2 ]

19 голосов
/ 12 июня 2011

TBH, mootools .bind, как вы его называете, это просто Function.bind в ES5 - и доступно изначально в браузерах, которые поддерживают спецификацию js 1.8.5 +.MooTools просто расширяет возможности браузеров, у которых его еще нет, но позволяет нативной реализации оставаться в прототипе - если он доступен.

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

Вы можете легко реализовать это как Function.prototype.bind декоратор, если он изначально недоступен, и использовать его, как показано в примере выше:

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

Как выКак видите, это немного сложнее, чем простой .apply / .call

Одна вещь, которую нужно учитывать, - если вам НУЖНО использовать bind или вы можете вместо этого сохранить ссылку.

например.

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

это занимает меньшую площадь, чем привязка функции в любом случае.это также дает вам правильную ссылку на this в качестве элемента триггера (event.target === this).вы найдете этот шаблон гораздо чаще в ядре mootools, чем в bind - хотя bind часто требуется, когда вы хотите назначить события методам класса, например:

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

В этом случае сохранение ссылкине будет работать, хотя вы можете переписать его как

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

Конкретная реализация jQuery: proxy - http://api.jquery.com/jquery.proxy/

0 голосов
/ 12 июня 2011

Все события, которые производятся на каком-либо элементе (например, «click» - одно из них), должны иметь свойство target, указывающее на этот элемент

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

JSFiddle

...