概述

ES6提供了类,给模块化带来了很大的帮助。在类里面绑定事件,一来是为了使得代码结构清晰,二来是为了可以使用类的变量和方法。但是,由于事件的回调函数并不是由类的实例对象触发,所以,事件回调函数里面并不能访问类的this变量。另外,我们也不希望事件回调函数对外暴露,免得调用者直接调用。

简单来说,我们就希望:
1. 事件回调函数要能访问类的this变量
2. 事件回调函数不能直接调用

如何访问类的this

方案一:将类的this保存成一个局部变量

this的指代是动态改变的,但是局部变量的指代却是明确的,并且,函数定义的局部变量在整个函数里面都可以用。所以,我们可以使用let that = this保存类的this变量。


class A{//绑定事件的方法bindEvent(){let that = this;this.button1.on('click',function(e){this.addClass('on'); //this指代所点的元素that.doSomething();  //that指向类的this})}doSomething(){//事件处理函数}//解绑事件unBindEvent(){this.button1.off();}}

这种方法只在使用jquery时有用,因为jquery解绑事件不需要提供回调函数,直接off就可以了。但是原生js需要提供回调函数也有它的道理,因为同一个元素的同一种事件可以绑定多个回调函数,所以你需要指出释放哪一个。

方案二:使用bind()改变this的指向

有类A,在A中要添加mousemove事件,根据需求写出下面代码:

class A{//添加事件addEvent(){document.addEventListener( 'mousemove', onMouseMove, false );}//添加事件removeEvent(){document.removeEventListener( 'mousemove', onMouseMove , false );}}//事件回调函数中
function onMouseMove(event){console.log(this);    //#document
}

但是,这样获取不到类的this。onMouseMovethis将会指向document。因为事件是添加到document上的,所以自然是由document触发事件并调用onMouseMove进行处理,所以onMouseMove中的this指向document

比较正确的做法是:使用bind()函数改变onMouseMovethis的指向,同时将事件回调函数移到类外面:

class A{//添加事件addEvent(){document.addEventListener( 'mousemove', onMouseMove.bind(this), false );}//添加事件removeEvent(){document.removeEventListener( 'mousemove', onMouseMove.bind(this) , false );}}//事件回调函数中
function onMouseMove(event){console.log(this);
}

但是这样仍然存在问题,事件移除不掉了!因为this.bind()每次调用都会返回一个新的函数,所以:

document.addEventListener( 'mousemove', onMouseMove.bind(this), false );

document.removeEventListener( 'mousemove', onMouseMove.bind(this), false );

两者的第二个参数并不相同。

正确的做法是: 将bind()的结果保存到一个变量中:

class A{constructor(){this._onMouseMove = onMouseMove.bind(this);    //看这里}//添加事件addEvent(){document.addEventListener( 'mousemove', this._onMouseMove , false );}//添加事件removeEvent(){document.removeEventListener( 'mousemove', this._onMouseMove , false );}}//事件回调函数中
function onMouseMove(event){console.log(this);
}

如何定义私有的事件回调函数

在Java中,不想对外暴露的方法可以定义为私有方法,但是ES6并没有提供私有方法,只能通过一些办法模拟。但是,事件回调函数比较特别,因为事件除了定义,还要移除,这会带来额外的麻烦。但还是有办法的:

使用Symbol变量来定义

const _onMouseMove = Symbol("_onMouseMove");
class A{constructor(){this[_onMouseMove] = onMouseMove.bind(this);}//添加事件addEvent(){document.addEventListener( 'mousemove', this[_onMouseMove] , false );}//添加事件removeEvent(){document.removeEventListener( 'mousemove', this[_onMouseMove] , false );}}//事件回调函数中
function onMouseMove(event){console.log(this);
}

Symbol("_onMouseMove")会产生一个唯一的值,这个值是在对象创建的时候才生成的,所以,调用者没有办法在写代码时知道这个值的,所以,就无法调用使用这个值命名的方法了,这样就定义了一个私有方法。


参考链接

在ES6类中绑定事件相关推荐

  1. 这就是为什么我们需要在React的类组件中绑定事件处理程序

    by Saurabh Misra 索拉·米斯拉(Saurabh Misra) 这就是为什么我们需要在React的类组件中绑定事件处理程序 (This is why we need to bind ev ...

  2. react中绑定点击事件_在React中绑定事件处理程序的最佳方法

    react中绑定点击事件 by Charlee Li 通过李李 在React中绑定事件处理程序的最佳方法 (The best way to bind event handlers in React) ...

  3. jQuery中绑定事件的几种方法

    以click事件为例,jQuery中绑定事件有三种方法: (1)target.click(function(){});  (2)target.bind("click",functi ...

  4. JQuery在循环中绑定事件的问题详解

    JQuery在循环中绑定事件的问题详解 有个页面上需要N个DOM,每个DOM里面的元素ID都要以数字结尾,比如说 ? 1 2 3 <input type="text" nam ...

  5. JS中绑定事件顺序(事件冒泡与事件捕获区别)

    在JS中,绑定的事件默认的执行时间是在冒泡阶段执行,而非在捕获阶段(重要),这也是为什么当父类和子类都绑定了某个事件,会先调用子类绑定的事件,后调用父类的事件.直接看下面实例 <!Doctype ...

  6. html移除click事件绑定,带你了解JQuery中绑定事件(bind())和移除事件(unbind())...

    本文主要向大家详细介绍了jQuery的绑定事件和移除事件的使用方法和示例分享,这里推荐给有需要的小伙伴们参考下. 有时候事件执行完了,想取消事件的效果可以通过一定的办法来处理.比如bind()(绑定事 ...

  7. React基础篇(六)React中绑定事件的注意点

    本小节讲述在 React 中为 button 设置点击事件的注意点 1 前言 在 React 中,事件的名称都是 React 中提供的,因此名称的首字母必须厉害 例如 onClick onMouseO ...

  8. 关于js中绑定事件失效问题

    相信很多开始学习前端开发的朋友都发生过绑定事件失效的问题,那么究竟是什么原因使得事件失效呢? 这里作者以jquery库编写作为例子. 第一种:直接失效. <html> <head&g ...

  9. JS中绑定事件的5种方式——以按钮绑定点击事件为例

    按钮 <button type="submit" id="btn">btn</button> 1. 第一种: $("#btn& ...

最新文章

  1. 《预训练周刊》第33期:艾伦AI研究所等 | 预训练语言模型的高效分层域适应
  2. Windows XP权限
  3. 做接口测试最重要的知识点
  4. jenkins 流水线(pipline)
  5. Spring注解标签详解@Autowired @Qualifier等
  6. 强连通Tarjan NYOJ 120 校园网络
  7. Sass mixin与extends、%placeholder、function
  8. Intellij IDEA更新SVN没有提示语
  9. ENVI二次开发时的注意事项
  10. AndroidStudio_安卓原生开发_java.io.FileNotFoundException: http://172.19.128.5(拒绝访问)---Android原生开发工作笔记157
  11. 安卓判断服务器返回的状态码,关于服务器返回的十四种常见HTTP状态码详解
  12. LR(1)项目集族的构造:如何确定前向搜索符
  13. Android NFC开发(一)
  14. 二叉堆/二项堆/斐波那契堆
  15. 【0.96OLED屏幕】原理图及SSD1306引脚功能
  16. 计算机键入命令,Win7系统安装软件提示命令行语法错误键入“ 命令/?”怎么办...
  17. 移动硬盘插到电脑后显示在设备和打印机解决办法
  18. hbase报错: ERROR: Can‘t get master address from ZooKeeper; znode data == null
  19. 【项目管理】【SVN】TortoiseSVN清理历史访问记录
  20. wchar_t的使用

热门文章

  1. vscode 遇到的迷之bug nvm is not compatible with the npm config prefix
  2. Oracle RDA(Remote Diagnostic Agent) 工具说明
  3. 新的编程语言研发契机思考
  4. springboot health检查
  5. c语言去除图像斑点,武汉理工-图像检测与处理技术-实验报告.doc
  6. php删除二位数组相同元素,删除去除二维数组中相同元素与数组重复值实例-PHP源码...
  7. php 添加样式,添加样式到php html电子邮件
  8. 实验16 编写包含多个功能子程序的中断例程
  9. 【剑指offer - C++/Java】9、变态跳台阶
  10. 使用Topshelf管理Windows服务