#javascript #jquery #mootools #mootools-events
#javascript #jquery #mootools #mootools-события
Вопрос:
Я пытаюсь переписать класс всплывающих подсказок Mootools в jQuery, используя этот плагин класса. Когда создается экземпляр моего класса, я подключаю прослушиватель событий к целевой ссылке, которая приведет к исчезновению всплывающей подсказки.
При обратных вызовах событий jQuery присваивает ключевое слово «this» целевому объекту события, поэтому, чтобы сохранить ссылку на свойства класса, который я использую apply()
, чтобы «this» означало экземпляр класса. По-видимому, это аналог в jQuery удобной bind()
функции Mootools от Mootools.
К сожалению, когда я использую apply()
, я теряю параметр события обратного вызова. Например, в этом бите я получаю ошибку «e не определено» во второй строке.
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))
Я упускаю какой-то трюк здесь? Кто-нибудь знает способ обойти эту проблему?
Ответ №1:
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-core, чем 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
Комментарии:
1. Димитар, ты ходячая энциклопедия JS! Спасибо за подробное объяснение. В этой ситуации ваше предложение ссылки кажется наилучшим, поэтому я бы сделал так: ` var self = this; this.target.bind(‘click’, function(e){ e.preventDefault(); self.toggleTip(); })` в моем методе инициализации, где toggleTip() — это отдельный обратный вызов click. Отличный совет, спасибо!
2. @Dimitar: Действительно отлично работает. спасибо. (at)в целом: обратите внимание, что этот метод функционального программирования называется каррированием ( dustindiaz.com/javascript-curry ). jQuery имеет аналогичное расширение прототипа имени метода ‘bind’, которое может несколько сбивать с толку, поскольку оно используется для обработки событий и объявлено в нефункциях. В jQuery также используется context в $.ajax для аналогичной цели.
Ответ №2:
Все события, которые выполняются для некоторого элемента (например, ‘click’ является одним из них), должны иметь целевое свойство, указывающее на этот элемент
var $this = $(e.target); // $this will be the clicked element
Комментарии:
1. Спасибо mkilmanas — это свойство, которое я надеялся использовать. К сожалению, когда я добавил apply () в конец моей функции, я потерял к ней доступ.