Ember.js Ember,mixin以检测视图/组件外部的单击
我正在编写一个Mixin来处理用户在视图/组件之外单击的情况 这是mixin:Ember.js Ember,mixin以检测视图/组件外部的单击,ember.js,Ember.js,我正在编写一个Mixin来处理用户在视图/组件之外单击的情况 这是mixin: App.ClickElsewhereMixin = Ember.Mixin.create({ onClickElsewhere: Ember.K, didRender: function() { this._super.apply(this, arguments); return $(document).on('click', this.get('onClickElsewhere'));
App.ClickElsewhereMixin = Ember.Mixin.create({
onClickElsewhere: Ember.K,
didRender: function() {
this._super.apply(this, arguments);
return $(document).on('click', this.get('onClickElsewhere'));
},
willDestroyElement: function() {
this._super.apply(this, arguments);
$(document).off('click', this.get('onClickElsewhere'));
},
});
我在我的组件中使用它:
onClickElsewhere: function() {
this.send('exitEditMode');
},
但当我运行它时,我得到:
TypeError: this.send is not a function
如何保持此上下文
解决方案:
为了让读者更容易阅读,这里是工作混音:
App.ClickElsewhereMixin = Ember.Mixin.create({
onClickElsewhere: Ember.K,
setupListener: Ember.on('didRender', function() {
// Set an event that will be fired when user clicks outside of the component/view
return $(document).on('click', $.proxy(this.get('onClickElsewhere'), this));
}),
removeListener: Ember.on('willDestroyElement', function() {
// Clean the previously defined event to keep events stack clean
return $(document).off('click', $.proxy(this.get('onClickElsewhere'), this));
}),
});
您有两个选择:
使用
使用
关闭
绑定
然而,并非所有浏览器都支持绑定
另外,我认为您需要在组件()中使用sendAction
而不是send
编辑:
使用调用
/在盖子下面应用
。有关call
/apply
vsbind
的讨论,请参阅。当前的答案不会检查单击是否实际位于元素之外–单击组件也会触发回调
以下是更新版本:
export default Ember.Mixin.create({
onOutsideClick: Ember.K,
handleOutsideClick: function(event) {
let $element = this.$();
let $target = $(event.target);
if (!$target.closest($element).length) {
this.onOutsideClick();
}
},
setupOutsideClickListener: Ember.on('didInsertElement', function() {
let clickHandler = this.get('handleOutsideClick').bind(this);
return Ember.$(document).on('click', clickHandler);
}),
removeOutsideClickListener: Ember.on('willDestroyElement', function() {
let clickHandler = this.get('handleOutsideClick').bind(this);
return Ember.$(document).off('click', clickHandler);
})
});
Greg answer有一个错误,这使得删除clickHandler事件无法工作。这意味着即使您销毁组件,您的clickevent也会触发
这是正确的版本
import Ember from 'ember';
export default Ember.Mixin.create({
onOutsideClick: Ember.K,
handleOutsideClick: function(event) {
let $element = this.$();
let $target = $(event.target);
if (!$target.closest($element).length) {
this.onOutsideClick();
}
},
setupOutsideClickListener: Ember.on('didInsertElement', function() {
let clickHandler = this.get('handleOutsideClick').bind(this);
return Ember.$(document).on('click', clickHandler);
}),
removeOutsideClickListener: Ember.on('willDestroyElement', function() {
let clickHandler = this.get('handleOutsideClick').bind(this);
return Ember.$(document).off('click', Ember.run.cancel(this, clickHandler));
})
});
余烬的做法是。这负责绑定和运行循环
App.ClickElsewhereMixin = Ember.Mixin.create({
onClickElsewhere: Ember.K,
setupListener: Ember.on('didRender', function() {
this.set('clickHandler', Ember.run.bind(this, this.onClickElsewhere));
Ember.$(document).click(this.get('clickHandler'));
}),
removeListener: Ember.on('willDestroyElement', function() {
Ember.$(document).off('click', this.get('clickHandler'));
}),
});
您可以使用lib。为我工作。事实上我发现我可以使用jQuery的$.proxy
功能,你觉得怎么样?谢谢!看起来有很多方法。这不起作用,因为执行bind
会创建对两个不同函数的引用,而removeEventListener
无法正确匹配它们。您的解决方案对我很有效,非常感谢。我认为问题在于我没有这样做。get('clickHandler'),因此这实际上不会正确地删除侦听器,在每个函数中执行this.get(…).bind(this)
会创建对不同函数的引用,因此document.off(…)
不会正确识别侦听器。它应该存储对绑定函数的引用,并在add/remove中使用相同的引用
import Ember from 'ember';
export default Ember.Mixin.create({
onOutsideClick: Ember.K,
handleOutsideClick: function(event) {
let $element = this.$();
let $target = $(event.target);
if (!$target.closest($element).length) {
this.onOutsideClick();
}
},
setupOutsideClickListener: Ember.on('didInsertElement', function() {
let clickHandler = this.get('handleOutsideClick').bind(this);
return Ember.$(document).on('click', clickHandler);
}),
removeOutsideClickListener: Ember.on('willDestroyElement', function() {
let clickHandler = this.get('handleOutsideClick').bind(this);
return Ember.$(document).off('click', Ember.run.cancel(this, clickHandler));
})
});
App.ClickElsewhereMixin = Ember.Mixin.create({
onClickElsewhere: Ember.K,
setupListener: Ember.on('didRender', function() {
this.set('clickHandler', Ember.run.bind(this, this.onClickElsewhere));
Ember.$(document).click(this.get('clickHandler'));
}),
removeListener: Ember.on('willDestroyElement', function() {
Ember.$(document).off('click', this.get('clickHandler'));
}),
});