javascript - 刺激 Controller : event listened multiple times; how do I remove event listeners and retain the Context?

标签 javascript event-listener stimulusjs

我的 HTML 页面上有以下 Controller :

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

此子 Controller 映射到以下 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.
    }
}

如您所见,connect() 上有一个事件监听器Stimulus Controller ,当它检测到事件被触发时,它会记录事件并操纵跨度目标。

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

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

myDivTarget.innerHTML= childControllerHTML;
...

现在myEvent被触发时,事件监听器不是一次选择它,而是两次(因为同一个事件被记录了两次)。随着子 HTML 的每次后续替换,事件都会比以前多记录一次。

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

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因为它不再找到 mySpanTargetthis 下.

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

最佳答案

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

初始化 Controller 时必须使用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 方法中丢失。

关于javascript - 刺激 Controller : event listened multiple times; how do I remove event listeners and retain the Context?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57318097/

相关文章:

javascript - 将函数传递给刺激

javascript - 将 `Intl.NumberFormat` 与 `maximumFractionDigits` 和 `maximumSignificantDigits` 一起使用

javascript - 在 android 级别 17 (4.2.2) 之前将数据传递给 webview 中的 javascript

javascript - 动态解绑eventListeners(垃圾回收)

javascript - StimulusJS 如何在连接上设置实例变量

ruby-on-rails - 如何在加载事件时将数据值传递给激励 Controller

javascript - Vue.js 单元测试 - 如何检查组件是否有方法?

javascript - 与/或逻辑与 .filter()

javascript - 如何覆盖原型(prototype)中的事件监听器?

php - FosUserBundle 在 FilterUserResponseEvent 中重定向