ค้นหาเว็บไซต์

javascript - การลบตัวฟังเหตุการณ์ที่ถูกเพิ่มด้วย bind


ใน JavaScript วิธีที่ดีที่สุดในการลบฟังก์ชันที่ถูกเพิ่มเป็นตัวฟังเหตุการณ์โดยใช้ bind() คืออะไร?

ตัวอย่าง

(function(){

    // constructor
    MyClass = function() {
        this.myButton = document.getElementById("myButtonID");
        this.myButton.addEventListener("click", this.clickListener.bind(this));
    };

    MyClass.prototype.clickListener = function(event) {
        console.log(this); // must be MyClass
    };

    // public method
    MyClass.prototype.disableButton = function() {
        this.myButton.removeEventListener("click", ___________);
    };

})();

วิธีเดียวที่ฉันนึกออกคือการติดตามผู้ฟังทุกคนที่ถูกเพิ่มด้วย bind

ตัวอย่างข้างต้นด้วยวิธีนี้:

(function(){

    // constructor
    MyClass = function() {
        this.myButton = document.getElementById("myButtonID");
        this.clickListenerBind = this.clickListener.bind(this);
        this.myButton.addEventListener("click", this.clickListenerBind);
    };

    MyClass.prototype.clickListener = function(event) {
        console.log(this); // must be MyClass
    };

    // public method
    MyClass.prototype.disableButton = function() {
        this.myButton.removeEventListener("click", this.clickListenerBind);
    };

})();

มีวิธีที่ดีกว่านี้ในการทำหรือไม่?

คำตอบ #1

แม้ว่าสิ่งที่ @machineghost พูดจะเป็นความจริง ว่าเหตุการณ์ถูกเพิ่มและลบในลักษณะเดียวกัน แต่ส่วนที่ขาดหายไปของสมการคือสิ่งนี้:

มีการสร้างการอ้างอิงฟังก์ชันใหม่หลังจากที่เรียกใช้ .bind()

ดู bind() เปลี่ยนการอ้างอิงฟังก์ชันหรือไม่? | วิธีการตั้งค่าอย่างถาวร?

ดังนั้น การเพิ่มหรือลบมัน ให้กำหนดการอ้างอิงไปยังตัวแปร:

var x = this.myListener.bind(this);
Toolbox.addListener(window, 'scroll', x);
Toolbox.removeListener(window, 'scroll', x);

สิ่งนี้ใช้ได้ตามที่ฉันคาดหวัง

คำตอบ #2

สำหรับผู้ที่มีปัญหานี้ขณะลงทะเบียน/ลบตัวฟังของคอมโพเนนต์ React กับ/จาก Flux store ให้เพิ่มบรรทัดด้านล่างไปยัง constructor ของคอมโพเนนต์ของคุณ:

class App extends React.Component {
  constructor(props){
    super(props);
    // it's a trick! needed in order to overcome the remove event listener
    this.onChange = this.onChange.bind(this);  
  }
  // then as regular...
  componentDidMount (){
    AppStore.addChangeListener(this.onChange);
  }
  
  componentWillUnmount (){
    AppStore.removeChangeListener(this.onChange);
  }

  onChange () {
    let state = AppStore.getState();
    this.setState(state);
  }
  
  render() {
    // ...
  }
  
}

บทความที่เกี่ยวข้อง