Удалить обработчик событий внутри функции с параметрами - PullRequest
0 голосов
/ 08 мая 2020

У меня есть несколько HTML форм на той же странице, которые переключаются последовательно одна за другой после отправки предыдущей. Пользователь может перемещаться между ними, поэтому мне нужно удалить прослушиватели событий отправки после их запуска, чтобы я мог снова подключить их при необходимости.

В настоящее время я подключаю обработчики событий отправки внутри «процесс рендеринга» для каждого из них, удаляя обработчик событий после выполнения функции следующим образом:

form.addEventListener('submit', submitStepOne)

  function submitStepOne(e) {
      e.preventDefault()
      sendData()
      form.removeEventListener('submit', submitStepOne)
  }

тот же код для нескольких элементов формы (submitStepTwo, submitStepThree…)

Поскольку я не хочу повторять один и тот же код, я хочу создать глобальную функцию «шаг отправки и go до следующего», которая, как я думал, может выглядеть примерно так:

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 для каждого из шагов, а также соответствующие функции для каждой страницы. PAGES.stepX.functions() вызывается каждый раз, когда шаг переключается с помощью toggleStep(step).

Однако я получаю Uncaught TypeError: Cannot read property 'preventDefault' of undefined. Как мне переписать функцию, чтобы я мог правильно передавать ей параметры?

Спасибо за любые подсказки!

1 Ответ

1 голос
/ 08 мая 2020

Вы передаете параметр event при присоединении функции submitStep, которая в этот момент имеет вид undefined.

Вам нужно будет изменить порядок аргументов submitStep, чтобы это событие было последний аргумент, затем частично примените stepNo и trigger, используя .bind().

Но в вашем коде есть еще одна ошибка. Вы пытаетесь удалить прослушиватель событий submitStep внутри него, который не будет работать после вызова .bind(), поскольку .bind() возвращает новую функцию. Я бы выделил регистрацию событий в отдельную функцию, которая создала бы оболочку вокруг обработчика событий и зарегистрировала бы оболочку как обработчик. Затем во время выполнения он вызовет фактический обработчик и отменит регистрацию.

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);
}
...