在ES6类中绑定事件
概述
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。onMouseMove的this將會指向document。因為事件是添加到document上的,所以自然是由document觸發事件并調用onMouseMove進行處理,所以onMouseMove中的this指向document。
比較正確的做法是:使用bind()函數改變onMouseMove中this的指向,同時將事件回調函數移到類外面:
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类中绑定事件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 西南科技大学OJ题 数字转换成字符061
- 下一篇: 软件项目管理(四)