Как это можно написать лучше / проще?

#javascript

#javascript

Вопрос:

Я практикую свои навыки работы с JavaScript, и мне пришла в голову идея кнопки, которая меняется на множество цветов каждый раз, когда я нажимаю на нее.

 const button = document.querySelector('button');
const colours = ['red', 'yellow', 'green', 'blue'];
let cycle = 1;
button.style.backgroundColor = colours[0];
button.addEventListener('click', e => {

    button.style.backgroundColor = colours[cycle];
    cycle  ;
    if (cycle == 4) {
        cycle = 0;
    };
});
  

Комментарии:

1. if Может быть cycle %= 4;

Ответ №1:

Вы могли бы использовать оператор постинкрементирования и по модулю. Кроме того, в обратном вызове события вы можете использовать e.target вместо button переменной напрямую:

 const button = document.querySelector('button');
const colours = ['red', 'yellow', 'green', 'blue'];
let cycle = 1;
button.style.backgroundColor = colours[0];
button.addEventListener('click', e => {
    e.target.style.backgroundColor = colours[cycle   % colours.length];
});  
 <button>M</button>  

Ответ №2:

Ваше решение довольно приятное и понятное, я могу просто показать вам, как это сделать без использования переменной цикла и использовать только функции colors array и array, чтобы получить текущую позицию и увеличить ее. Я использую остаток от длины массива division by colors, чтобы оставаться в размере массива

 const button = document.querySelector('button');
const colours = ['red', 'yellow', 'green', 'blue'];
button.style.backgroundColor = colours[0]
button.addEventListener('click', e => {
    button.style.backgroundColor = colours[(colours.indexOf(button.style.backgroundColor) 1)%colours.length];
});  
 <button>Click me!</button>  

Комментарии:

1. Спасибо, я думал, что мой должен выглядеть примерно так

Ответ №3:

Используя другой и более функциональный подход к программированию — вы могли бы создать cycleColours функцию, которая использует замыкание и возвращает функцию для циклического перебора цветов, которая возвращает следующий в массиве при каждом вызове.

Таким образом, вы можете повторно использовать эту функцию в другом месте и абстрагирует логику от обработчика щелчков от button .

 const cycleColours = (coloursArray = []) => {
  const colours = coloursArray;
  let index = 0;

  const incrementIndex = () => {
    index  ;
    if (index >= colours.length) index = 0;
  };

  return () => {
    const colour = colours[index];
    incrementIndex();
    return colour;
  };
};

const coloursButtonOne = ['red', 'yellow', 'green', 'blue']
const getButtonOneColour = cycleColours(coloursButtonOne);

const coloursButtonTwo = ['yellow', 'pink', 'purple', 'white']
const getButtonTwoColour = cycleColours(coloursButtonTwo);

const buttonOne = document.querySelector('button#one');
const buttonTwo = document.querySelector('button#two');

buttonOne.style.backgroundColor = getButtonOneColour();
buttonTwo.style.backgroundColor = getButtonTwoColour();

buttonOne.addEventListener('click', e => {
    e.target.style.backgroundColor = getButtonOneColour();
});

buttonTwo.addEventListener('click', e => {
    e.target.style.backgroundColor = getButtonTwoColour();
});  
 <button id="one">Click Me!</button>
<button id="two">Click Me!</button>  

Комментарии:

1. Я не думал о том, что я сделаю, чтобы создать еще одну кнопку. Спасибо

Ответ №4:

Это мои пять центов:

Моя стратегия такова

  1. Стилизуйте как можно больше с помощью CSS. Попытайтесь предотвратить встроенные стили или настройку стиля с помощью JavaScript.
  2. Не добавляйте EventListeners напрямую к элементу. Вместо этого добавьте EventListeners в документ. Используйте пузырящееся событие.
  3. Инкапсулировать имена переменных (для этого и нужен IIFE)

 // IIFE to encapsulate variable names
(function(w, d) {
  const className = 'color-cycle';
  const selector = `.${className}`;
  const cycles = 4

  // add EventListener to document not the element
  d.addEventListener('click', e => {
    // check the target of the event, if it is inside the button
    const button = e.target.closest(selector);
    if (button) {
      // Use `data-` attribute to store cycle
      button.dataset.cycle = (parseInt(button.dataset.cycle || 0)   1) % cycles
    }
  });
}(window, document));

// For demonstration purposes
(function(d) {
  const selector = `#add-button`;
  const className = 'color-cycle';

  d.addEventListener('click', e => {
    const button = e.target.closest(selector);
    if (button) {
      const newButton = d.createElement('button');
      newButton.classList.add(className);
      newButton.textContent = 'Button'
      d.body.appendChild(newButton);
      d.body.appendChild(d.createTextNode("n"))
    }
  })
}(document));  
 button {
  padding: 10px;
  border-radius: 10px;
  border: 1px solid gray;
  outline: none;
}

button:hover,
button:focus {
  border-color: black;
  border-width: 2px;
  padding: 9px;
}

button.color-cycle {
  display: inline-block;
  margin: 2px;
}
button.color-cycle,
button.color-cycle[data-cycle="0"] {
  background-color: red;
}

button.color-cycle[data-cycle="1"] {
  background-color: yellow;
}

button.color-cycle[data-cycle="2"] {
  background-color: green;
}

button.color-cycle[data-cycle="3"] {
  background-color: blue;
}  
 <button id="add-button">Add Button</button><br><br>

<button class="color-cycle">Button 1</button>
<button class="color-cycle">Button 2</button>
<button class="color-cycle">Button 3</button>
<button class="color-cycle">Button 4</button>  

Комментарии:

1. Спасибо, я раньше не видел [data-cycle], обязательно изучу его

2. Это термин, cycle который я изобрел. На этом этапе вы могли бы установить что угодно

3.@See: developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/…*

4. @See developer.mozilla.org/en-US/docs/Web/API/HTMLOrForeignElement/…

5. @See developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors