【问题标题】:Stimulus controller: event listened multiple times; how do I remove event listeners and retain the Context?刺激控制器:多次监听事件;如何删除事件侦听器并保留上下文?
【发布时间】:2019-12-10 14:05:03
【问题描述】:

我的 HTML 页面上有以下控制器:

...
<div data-controller="parent">
    <div data-target="parent.myDiv">
        <div data-controller="child">
            <span data-target="child.mySpan"></span>
        </div>
    </div>
</div>
...

此子控制器映射到以下child_controller.js 类:

export default class {
    static targets = ["mySpan"];

    connect() {
        document.addEventListener("myEvent", (event) => this.handleMyEvent(event));
    }

    handleMyEvent(event) {
        console.log(event);
        this.mySpanTarget; // Manipulate the span. No problem.
    }
}

如您所见,Stimulus 控制器的connect() 上有一个事件监听器,当它检测到事件被触发时,它会记录该事件并操作 span 目标。

当我从我的parent_controller.js 替换目标myDiv 的内容时出现问题:

...
let childControllerHTML = "<div data-controller="child">...</div>"

myDivTarget.innerHTML= childControllerHTML;
...

现在myEvent 已启动,事件侦听器不会选择一次,而是两次(因为相同的事件被记录了两次)。每次后续替换子 HTML 时,事件都会比以前多记录一次。

我知道可以利用document.removeEventListener 来防止旧控制器仍然监听事件:

export default class {
    static targets = ["mySpan"];

    connect() {
        this.myEventListener = document.addEventListener("myEvent", (event) => this.handleMyEvent(event));
    }

    disconnect() {
        document.removeEventListener("myEvent", this.myEventListener);
    }

    handleMyEvent(event) {
        console.log(event);
        this.mySpanTarget; // FAILS. Can't find span.
    }
}

但是这样做会使handleMyEvent 方法丢失context,因为它不再在this 下找到mySpanTarget

如何从我已经无法访问的子控制器中删除侦听器,因为它不再在 DOM 中,同时保留上下文?

【问题讨论】:

    标签: javascript event-listener stimulusjs


    【解决方案1】:

    我在StimulusJS's Discourse page找到了答案。

    初始化控制器时必须使用bind方法:

    export default class {
        static targets = ["mySpan"];
    
        initialize() {
            this.boundHandleMyEvent = this.handleMyEvent.bind(this);
        }
    
        connect() {
            document.addEventListener("myEvent", this.boundHandleMyEvent);
        }
    
        disconnect() {
            document.removeEventListener("myEvent", this.boundHandleMyEvent);
        }
    
        handleMyEvent(event) {
            console.log(event);
            this.mySpanTarget; // Manipulate the span. No problem.
        }
        ...
    }
    

    现在,事件只被监听一次,上下文不会在handleMyEvent 方法中丢失。

    【讨论】:

      猜你喜欢
      • 2018-09-04
      • 1970-01-01
      • 2012-09-10
      • 1970-01-01
      • 2017-01-16
      • 1970-01-01
      • 2022-08-03
      • 1970-01-01
      • 2011-05-23
      相关资源
      最近更新 更多