Ember.js Ember,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'));

我正在编写一个Mixin来处理用户在视图/组件之外单击的情况

这是mixin:

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
    vs
    bind
    的讨论,请参阅。当前的答案不会检查单击是否实际位于元素之外–单击组件也会触发回调

    以下是更新版本:

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