Событие слушали несколько раз; Как удалить прослушиватели событий и сохранить контекст на контроллере Stimulus?
У меня есть следующий контроллер на моей странице 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.handleEvent(event));
}
handleEvent(event) {
console.log(event);
this.mySpanTarget; // Manipulate the span. No problem.
}
}
Как вы можете видеть, на connect()
контроллера Stimulus, и когда он обнаруживает, что событие было запущено, он регистрирует событие и манипулирует целью span.
Проблема возникает, когда я заменяю содержимое цели myDiv
от моего parent_controller.js
:
...
let childControllerHTML = "<div data-controller="child">...</div>"
myDivTarget.innerHTML= childControllerHTML;
...
Теперь, когда myEvent
когда его зажигают, слушатель выбирает его не один, а два раза. Это означает, что событие обрабатывается дважды, потому что я получаю одно и то же событие, записанное в журнал. При каждой последующей замене дочернего HTML событие регистрируется еще раз, чем раньше.
Я знаю, что можно использовать document.removeEventListener
чтобы старый контроллер все еще не слушал события:
export default class {
static targets = ["mySpan"];
connect() {
this.boundHandleEvent = document.addEventListener("myEvent", (event) => this.handleEvent(event));
}
disconnect() {
document.removeEventListener("myEvent", this.boundHandleEvent);
}
handleEvent(event) {
console.log(event);
this.mySpanTarget; // FAILS. Can't find span.
}
}
Но, делая это так, я handleEvent
метод потерять context
как он больше не находит mySpanTarget
под this
,
Как я могу удалить слушателя из дочернего контроллера, к которому у меня уже нет доступа, поскольку он больше не находится в DOM, при этом сохраняя контекст?
1 ответ
Я нашел ответ на странице Дискурса StimulusJS.
Нужно использовать bind
метод:
export default class {
static targets = ["mySpan"];
initialize() {
this.boundHandleEvent = this.handleEvent.bind(this);
}
connect() {
document.addEventListener("myEvent", this.boundHandleEvent);
}
disconnect() {
document.removeEventListener("myEvent", this.boundHandleEvent);
}
handleEvent(event) {
console.log(event);
this.mySpanTarget; // Manipulate the span. No problem.
}
...
}
Теперь событие прослушивается только один раз, и контекст не теряется внутри handleEvent
метод.