ES6 Class封装滚动组件时如何在事件回调中访问类实例变量
解决方案
你遇到的是ES6类中事件回调this指向丢失的典型问题,有三种常用的可靠解决方法:
方法1:构造函数中手动绑定this
在构造函数内将类方法的this强制绑定到当前实例,兼容性最好,所有支持ES6 Class的环境都可正常运行:
class HoriScroll { constructor(id) { this.target = document.getElementById(id); // 提前绑定this到类实例 this.slideStart = this.slideStart.bind(this); this.slideMove = this.slideMove.bind(this); this.target.addEventListener('touchstart',this.slideStart,{passive:true}); this.target.addEventListener('touchmove',this.slideMove,{passive:true}); // 状态直接存储在实例上,无需挂载到DOM的dataset this.startX = null; this.startTime = null; this.movePending = false; } slideStart(e) { if (1 === e.changedTouches.length) { // 此时this指向HoriScroll类实例,可直接读写实例属性 this.startX = e.changedTouches[0].screenX; this.startTime = Date.now(); } } }
方法2:类字段箭头函数写法
利用箭头函数this继承外层作用域的特性,直接用箭头函数定义类方法,无需手动绑定,写法更简洁:
class HoriScroll { // 直接定义实例属性 startX = null; startTime = null; movePending = false; constructor(id) { this.target = document.getElementById(id); this.target.addEventListener('touchstart',this.slideStart,{passive:true}); this.target.addEventListener('touchmove',this.slideMove,{passive:true}); } // 箭头函数自动绑定this到类实例 slideStart = (e) => { if (1 === e.changedTouches.length) { this.startX = e.changedTouches[0].screenX; this.startTime = Date.now(); } } slideMove = (e) => { // 同理可直接访问所有实例属性 } }
方法3:事件绑定时用箭头函数包裹
不需要改动原有方法定义,绑定事件时用箭头函数包裹回调即可,适合临时调整的场景:
constructor(id) { this.target = document.getElementById(id); // 箭头函数的this继承自构造函数作用域的实例 this.target.addEventListener('touchstart', (e) => this.slideStart(e), {passive:true}); this.target.addEventListener('touchmove', (e) => this.slideMove(e), {passive:true}); }
注意:如果后续需要移除事件监听,需要把箭头函数存为实例变量,否则无法匹配到对应的回调函数完成移除。
三种方法都可以完全解决this指向问题,原本存储在dataset的状态都可以迁移为类实例属性,代码可维护性会明显提升。
内容的提问来源于stack exchange,提问作者DroidOS
相关产品推荐
相关产品推荐

