在 JavaScript 按钮事件中,如何避免代码重复(当每个按钮都具有相似功能时)

In JavaScript button events, how do I avoid code duplication (when every button has similar functions)

我是 JavaScript 的新手,正在尝试找出如何避免 对事件侦听器使用重复代码。

我有一个带有几个按钮的 html 页面。

在这个有 2 个按钮的例子中,(id'd trip_1trip_2 )我想要有按钮 单击时闪烁蓝色,然后在几毫秒后继续执行下一步代码

代码有效,但重复太多。

这里我为每个按钮获取一个常量,然后添加一个事件监听器 给它。监听器做的几乎一样。

是否有推荐的方法来避免为每个按钮编写重复的侦听器?

我更喜欢让一个事件侦听器侦听所有按钮,然后对按下的按钮做出反应。

let step_change_ms = 250

function setCurrentStep(step) {
  // removed, this function hides the elements not in use and
  // shows the currently needed ones
}

const tripButton1 = document.getElementById('trip_1');
tripButton1.addEventListener('click', event => {
    event.preventDefault();
    tripButton1.style.backgroundColor = "blue";

    buttons_active = false;
    myBooking.trips = 1;
    setTimeout(function () {
        setCurrentStep('step4')
    }, step_change_ms);
    setTimeout(function () {
        tripButton1.style.backgroundColor = "white";
    }, step_change_ms);
});

const tripButton2 = document.getElementById('trip_2');
tripButton2.addEventListener('click', event => {
    event.preventDefault();
    tripButton2.style.backgroundColor = "blue";
    buttons_active = false;
    myBooking.trips = 2;
    setTimeout(function () {
        setCurrentStep('step4')
    }, step_change_ms);
    setTimeout(function () {
        tripButton2.style.backgroundColor = "white";
    }, step_change_ms);
});

你可以这样做(虽然我不喜欢拆分 id 来获取号码,但这是一般的想法):

let step_change_ms = 250

function setCurrentStep(step) {
  // removed, this function hides the elements not in use and
  // shows the currently needed ones
}

const myBooking = { trips: 0 };

document.querySelectorAll('[id^=trip_]').forEach((el) => {
    const [ , num ] = el.id.split('_');
    el.addEventListener('click', event => {
        event.preventDefault();
        el.style.backgroundColor = "blue";

        buttons_active = false;
        myBooking.trips = parseInt(num);
        console.log(myBooking);
        setTimeout(function () {
            setCurrentStep('step4')
        }, step_change_ms);
        setTimeout(function () {
            el.style.backgroundColor = "white";
        }, step_change_ms);
    });
});
<button id="trip_1">1</button>
<button id="trip_2">2</button>

或者,也许更好:

let step_change_ms = 250

function setCurrentStep(step) {
  // removed, this function hides the elements not in use and
  // shows the currently needed ones
}

const myBooking = { trips: 0 };
const addListener = (el, num) => {
    el.addEventListener('click', event => {
        event.preventDefault();
        el.style.backgroundColor = "blue";

        buttons_active = false;
        myBooking.trips = num;
        console.log(myBooking);
        setTimeout(function () {
            setCurrentStep('step4')
        }, step_change_ms);
        setTimeout(function () {
            el.style.backgroundColor = "white";
        }, step_change_ms);
    });
}

addListener(document.getElementById('trip_1'), 1);
addListener(document.getElementById('trip_2'), 2);
    <button id="trip_1">1</button>
    <button id="trip_2">2</button>

我认为解决方案非常简单。您需要创建一个单独的参数化函数,根据传递的参数更改行为。例如,您可以创建一个带有一些参数的工厂函数和 returns 一个新函数(事件处理程序)。代码将如下所示:

function createEventListener(btn, trips) {
    return function(event) {
       event.preventDefault();
       btn.style.backgroundColor = "blue";
       buttons_active = false;
       myBooking.trips = trips;
       setTimeout(function () {
           setCurrentStep('step4')
       }, step_change_ms);
       setTimeout(function () {
          btn.style.backgroundColor = "white";
       }, step_change_ms);
    }
}
const tripButton1 = document.getElementById('trip_1');
tripButton1.addEventListener('click', createEventListener(tripButton1, 1));
const tripButton2 = document.getElementById('trip_2');
tripButton2.addEventListener('click', createEventListener(tripButton2, 2));

P.S。请注意,这个例子可能有一些错别字,因为我没有验证它,但我希望这个想法是清楚的。

P.P.S。尝试编写 DRY (https://uk.wikipedia.org/wiki/Don%27t_repeat_yourself) code, but better focus on SOLID (https://en.wikipedia.org/wiki/SOLID) 原则并不总是好的