You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
classBase{a=1;constructor(){document.querySelector("#click").addEventListener("click",this.handleClick);}handleClick=()=>{console.log("click",this.a);// click 1};}classDerivedextendsBase{handleClick(){super.handleClick();console.log("click2",this.a);// not run}}newDerived();
事件绑定和类继承都是很常用的东西, 当它俩结合起来时, 可能并不会像你所想的那样工作
来看一个最简单的例子, 在构造函数中绑定 click 事件, 点击后打印
"click"
和this.a
在该例中
this.a
会打印什么呢? 会打印undefined
, 因为handleClick
的 this 指向是 button dom 对象, dom 对象没有 a 属性首先, 可以用箭头函数来解决 this 指向问题, 在 react 中这种写法很常见, 这没什么问题
但是, 当与类继承相结合时会怎样呢? 如下的例子中, 派生类继承基类并重载
handleClick
方法点击后会并不会输出
"click2"
, 因为基类的handleClick
是定义在实例属性上, 而派生类的handleClick
是定义在派生类的原型链上, 实例属性访问优先级大于原型链, 所以根本没执行到派生类的handleClick
尝试通过原型链直接调用派生类的
handleClick
, 注意! 由于是直接调用的,super.handleClick()
不可用需要注释掉会输出
click2 1
, 但是不会调到基类方法修改一下, 将基类改为普通函数, 并在绑定事件时 bind this, 这就是我们所期望的效果了
接下来, 我们增加一个需求, 新增一个按钮用来取消事件订阅
如下所示, 点击 unsubscribe 按钮后调用 removeEventListener 取消事件订阅, 但是并不起作用(包括注释那行)
为什么呢? 因为订阅和取消订阅的并不是同一个方法, 订阅时的 bind 调用会返回一个全新函数, 由于没有保存该函数引用, 调用 removeEventListener 也就无法将其取消订阅
怎么解决呢?
只要将 bind 后的实例保存下来即可, 这样就能确保订阅和取消订阅的是同一方法了, 完美达成期望
还可以用 (https://www.npmjs.com/package/autobind-decorator) 装饰器自动完成 bind 操作
总结
The text was updated successfully, but these errors were encountered: