如何在JavaScript中临时删除eventListener?

问题描述 投票:0回答:1

每当有人选择休息日的日期(例如星期六或星期日,它可能是一系列关闭日中的任何一天)时,我想呈现错误。

我有 HTML:

<div>
  <input type="date" id="date-input">
</div>

<br>

<div id="error-container">
</div>

CSS:

.d-error{
  background: orangered;
  color: white;
  padding: 4px 8px;
}

这是 JavaScript:

'use strict';

const dateInput = document.getElementById('date-input');
const errorContainer = document.getElementById('error-container');
const closingDays = [0, 6];
const weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday','Friday', 'Saturday'];

const displayError = function ({ parentEl, message, position = 'prepend', durationSec = 0 }) {
  const errorElement = document.createElement('p');
  errorElement.classList.add('d-error');
  errorElement.textContent = message;
  parentEl[position](errorElement);

  if (durationSec) {
    setTimeout(() => {
      errorElement.remove();
    }, durationSec * 1000);
  }
};

const handleDateChange = function (event) {
  const selectedDay = new Date(event.currentTarget.value).getDay();

  if (closingDays.includes(selectedDay)) {
    displayError({
      parentEl: errorContainer,
      message: `We are closed on ${weekDays[selectedDay]}. Please select another day.`,
      durationSec: 5
    });

    event.currentTarget.value = '';
  }
};

dateInput.addEventListener('change', handleDateChange);

这可行,但错误会呈现两次。一次是由于用户更改,一次是由于以编程方式更改输入值

event.currentTarget.value = '';
。那么,如何暂时删除
change
事件监听器并重新附加到它呢?或者有其他方法可以解决这个问题吗?

我尝试过:

const handleDateChange = function(event) {
  ...

  event.currentTarget.removeEventListener('change', handleDateChange);
  event.currentTarget.value = '';  
  event.currentTarget.addEventListener('change', handleDateChange);

  ...
}

但这并没有解决问题。

更新:

首先,正如@Sebastian 所指出的,以编程方式设置输入的值不会触发

change
事件。所以一定还有其他原因导致事件触发两次。

我非常抱歉没有在 Firefox 以外的其他浏览器中进行测试。这个问题似乎只出现在 Firefox 中,因为在基于 chromium 的浏览器中,一切都按预期工作(尽管在 Firefox android 中工作)。所以,我猜测这是 Firefox 中的某种错误,但我个人无法确认。请尝试在不同的浏览器中运行代码片段。

'use strict';

const dateInput = document.getElementById('date-input');
const errorContainer = document.getElementById('error-container');
const closingDays = [0, 6];
const weekDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

const displayError = function({
  parentEl,
  message,
  position = 'prepend',
  durationSec = 0
}) {
  const errorElement = document.createElement('p');
  errorElement.classList.add('d-error');
  errorElement.textContent = message;
  parentEl[position](errorElement);

  if (durationSec) {
    setTimeout(() => {
      errorElement.remove();
    }, durationSec * 1000);
  }
};

const handleDateChange = function(event) {
  const selectedDay = new Date(event.currentTarget.value).getDay();

  if (closingDays.includes(selectedDay)) {
    displayError({
      parentEl: errorContainer,
      message: `We are closed on ${weekDays[selectedDay]}. Please select another day.`,
      durationSec: 5
    });

    event.currentTarget.value = '';
  }
};

dateInput.addEventListener('change', handleDateChange);
.d-error {
  background: orangered;
  color: white;
  padding: 4px 8px;
}
<div>
  <input type="date" id="date-input">
</div>

<br>

<div id="error-container">
</div>

javascript dom dom-events
1个回答
0
投票

这里是一个较短版本的代码片段,用于在 Firefox (121) 中重现该错误。 OP 是正确的,第二个事件实际上是由以编程方式设置输入字段的值引起的(情况不应该如此)。但是,第二个事件中打印到控制台的值与第一个事件的值相同。此外,在事件处理程序之外设置值根本不会触发事件(应该如此)。因此,应该将此行为报告给 https://bugzilla.mozilla.org/ .

function onChange(event) {
  console.log('changed to ' + dateInput.value)
  dateInput.value = ''; // somehow triggers a second event
};

dateInput.addEventListener('change', onChange);
dateInput.value = '2024-02-07'; // does not trigger the event!
<div>
  <input type="date" id="dateInput">
</div>

© www.soinside.com 2019 - 2024. All rights reserved.