使用参数删除函数内部的事件处理程序
Remove event handler inside function with parameters
我在同一页面上有一些 HTML 表单,在提交前一个表单后,它们一个接一个地依次切换。用户可以在它们之间来回导航,所以我需要在触发事件监听器后删除它们,这样我就可以在需要时重新附加它们。
我目前在 "rendering process" 中为它们中的每一个附加提交事件处理程序,在执行函数后删除事件处理程序,如下所示:
form.addEventListener('submit', submitStepOne)
function submitStepOne(e) {
e.preventDefault()
sendData()
form.removeEventListener('submit', submitStepOne)
}
多个表单元素的相同代码(submitStepTwo
、submitStepThree
…)
因为我不想一直重复相同的代码,所以我想创建一个全局 "submit step and go to next one" 函数,我认为它看起来像这样:
const submitStep = (event, stepNo, trigger) => {
event.preventDefault()
toggleStep(stepNo)
trigger.removeEventListener('submit', submitStep)
}
我想我可以像这样将事件处理程序附加到提交按钮,使用 .bind()
(来自 的提示):
PAGES.step3.functions = function() {
console.log('step 3')
let trigger = this.domElement.querySelector('form')
trigger.addEventListener('submit', submitStep.bind(null, event, 4, trigger))
}
PAGES
是一个对象,其中包含每个步骤的 DOM 元素以及每个页面的相应功能。每次使用 toggleStep(step)
切换步骤时都会调用 PAGES.stepX.functions()
。
但是,我收到 Uncaught TypeError: Cannot read property 'preventDefault' of undefined
。我怎样才能重写这个函数,以便我可以正确地将参数传递给它?
感谢任何提示!
您在附加 submitStep
函数时传递了 event
参数,此时为 undefined
.
您需要重新排列 submitStep
的参数,以便事件成为最后一个参数,然后使用 .bind()
部分应用 stepNo
和 trigger
。
但是您的代码中还有另一个错误。您正在尝试删除其中 submitStep
的事件侦听器,这在调用 .bind()
后将不起作用,因为 .bind()
returns 是一个新函数。我会将事件注册分离到一个单独的函数中,这将在事件处理程序周围创建一个包装器并将包装器注册为处理程序。然后在执行期间它会调用实际的处理程序并注销自己。
const addEventListenerOnce = (trigger, eventName, handler) => {
// Create a function that will be registered as event handler
const handlerWrapper = (event) => {
// Call the actual handler
handler(event);
// Remove the registered wrapper
trigger.removeEventListener(eventName, handlerWrapper);
};
// Register the wrapping function as event listener
trigger.addEventListener(eventName, handlerWrapper);
};
const submitStep = (stepNo, event) => {
event.preventDefault();
toggleStep(stepNo);
}
PAGES.step3.functions = function() {
console.log('step 3')
let trigger = this.domElement.querySelector('form')
// Only stepNo is applied, event is left
// Function signature would be then (event) => void
const submitHandler = submitStep.bind(null, 4);
// Register the submit handler to be called once
addEventListenerOnce(trigger, 'submit', submitHandler);
}
我在同一页面上有一些 HTML 表单,在提交前一个表单后,它们一个接一个地依次切换。用户可以在它们之间来回导航,所以我需要在触发事件监听器后删除它们,这样我就可以在需要时重新附加它们。
我目前在 "rendering process" 中为它们中的每一个附加提交事件处理程序,在执行函数后删除事件处理程序,如下所示:
form.addEventListener('submit', submitStepOne)
function submitStepOne(e) {
e.preventDefault()
sendData()
form.removeEventListener('submit', submitStepOne)
}
多个表单元素的相同代码(submitStepTwo
、submitStepThree
…)
因为我不想一直重复相同的代码,所以我想创建一个全局 "submit step and go to next one" 函数,我认为它看起来像这样:
const submitStep = (event, stepNo, trigger) => {
event.preventDefault()
toggleStep(stepNo)
trigger.removeEventListener('submit', submitStep)
}
我想我可以像这样将事件处理程序附加到提交按钮,使用 .bind()
(来自 的提示):
PAGES.step3.functions = function() {
console.log('step 3')
let trigger = this.domElement.querySelector('form')
trigger.addEventListener('submit', submitStep.bind(null, event, 4, trigger))
}
PAGES
是一个对象,其中包含每个步骤的 DOM 元素以及每个页面的相应功能。每次使用 toggleStep(step)
切换步骤时都会调用 PAGES.stepX.functions()
。
但是,我收到 Uncaught TypeError: Cannot read property 'preventDefault' of undefined
。我怎样才能重写这个函数,以便我可以正确地将参数传递给它?
感谢任何提示!
您在附加 submitStep
函数时传递了 event
参数,此时为 undefined
.
您需要重新排列 submitStep
的参数,以便事件成为最后一个参数,然后使用 .bind()
部分应用 stepNo
和 trigger
。
但是您的代码中还有另一个错误。您正在尝试删除其中 submitStep
的事件侦听器,这在调用 .bind()
后将不起作用,因为 .bind()
returns 是一个新函数。我会将事件注册分离到一个单独的函数中,这将在事件处理程序周围创建一个包装器并将包装器注册为处理程序。然后在执行期间它会调用实际的处理程序并注销自己。
const addEventListenerOnce = (trigger, eventName, handler) => {
// Create a function that will be registered as event handler
const handlerWrapper = (event) => {
// Call the actual handler
handler(event);
// Remove the registered wrapper
trigger.removeEventListener(eventName, handlerWrapper);
};
// Register the wrapping function as event listener
trigger.addEventListener(eventName, handlerWrapper);
};
const submitStep = (stepNo, event) => {
event.preventDefault();
toggleStep(stepNo);
}
PAGES.step3.functions = function() {
console.log('step 3')
let trigger = this.domElement.querySelector('form')
// Only stepNo is applied, event is left
// Function signature would be then (event) => void
const submitHandler = submitStep.bind(null, 4);
// Register the submit handler to be called once
addEventListenerOnce(trigger, 'submit', submitHandler);
}