Javascript 帮我干这个

Javascript Help me make this DRY

我想让这段代码符合 DRY 原则,我看到我重复了一遍,但必须有办法将这段代码缩短为不那么 WET 的代码。目标是制作一个在将鼠标悬停在卡片上时播放声音的功能,它可以工作,但截至目前代码是 WET。

<header class="card" id="play_1">
  <audio>
    <source src="/voices/sound1"></source>
  </audio>
</header>


<header class="card" id="play_2">
  <audio>
    <source src="/voices/sound2"></source>
  </audio>
</header>

<header class="card" id="play_3">
  <audio>
    <source src="/voices/sound3"></source>
  </audio>
</header>
window.onload=function(){

var playHover = document.getElementById('play_1'),
    audios = document.querySelectorAll('audio');
console.log(audios);


playHover.addEventListener('mouseover', function() {
[].forEach.call(audios, function(audio) {
  audio.play();
});
}, false);

var playHover2 = document.getElementById('play_2'),
    audios = document.querySelectorAll('audio');
console.log(audios);


playHover2.addEventListener('mouseover', function() {
[].forEach.call(audios, function(audio) {
  audio.play();
});
}, false);

var playHover3 = document.getElementById('play_3'),
    audios = document.querySelectorAll('audio');
console.log(audios);


playHover3.addEventListener('mouseover', function() {
[].forEach.call(audios, function(audio) {
  audio.play();
});
}, false);
}

我尝试制作一个 for 循环来输入 id 的号码,但我没能成功 我的 for 循环主要来自其他有类似干燥问题的人

window.onload=function(){

for ( var i = 1; i < 4; i++ ) window.onload();
var playHover = document.getElementById('play_' + i),
    audios = document.querySelectorAll('audio');
console.log(audios);


playHover.addEventListener('mouseover', function() {
[].forEach.call(audios, function(audio) {
  audio.play();
});
}, false);
}

跳过将其声明为变量:

for (let i = 1; i < 3; i++) {

document.getElementById('play_ + ' i),
    audios = document.querySelectorAll('audio').addEventListener('mouseover', function() {
[].forEach.call(document.querySelectorAll('audio'), function(audio) {
  audio.play();
});
}, false)
}

不幸的是,因为我没有任何明显的 audio-streaming 服务访问权限(允许他们的内容自由流式传输),所以我无法为您提供很多演示。

但是,我建议根据以下观察对您的代码进行以下修改:

  • 您正在使用的每个元素的 DOM 与所有其他元素具有相同的结构,
  • 你在每个实例中都在有效地做同样的事情,
  • 没有必要使用 id 属性 和
  • 绑定 event-handler
  • 变量可以根据需要在函数内部实例化。

考虑到这一点,我建议如下 JavaScript(解释性注释在代码中):

// here we're using an alternative EventTarget.addEventListener() to bind the
// event-handling once the window, and contents, have loaded and are ready:

// the empty parentheses are used because we're not passing any arguments to
// the enclosed function; using EventTarget.addEventListener() makes the
// Event Object available automatically, but we don't need to use that
// in this instance:
window.addEventListener('DOMContentLoaded', () => {

  // defining the named function to be bound as the event-handler; in this
  // function we pass in a reference to the Event Object passed by
  // EventTarget.addEventListener():
  const playAudio = (evt) => {
    // from the Event Object we retrieve the <header> element to which
    // the function was bound, and triggered:
    let currentHeader = evt.currentTarget,
      // from the <header> we use Element.querySelector() to find
      // the first (if any) <audio> element descendant:
      currentAudio = currentHeader.querySelector('audio'),
      // finding all <audio> elements in the document (since the way
      // I read your code it seemed like you were playing all <audio>
      // elements, but I imagine I was wrong:
      allAudios = document.querySelectorAll('audio');

    // if you want to play just the <audio> element from the <header>
    // that your user is hovering over:
    currentAudio.play();
    // if, instead, you do want to play all <audios> then we can
    // iterate over the NodeList of <audio> elements using
    // NodeList.prototype.forEach():
    allAudios.forEach(
      // passing in a reference the current <audio> element, and
      // calling its play() method:
      (audioElement) => audioElement.play()
    );
  };

  // using document.querySelectorAll() to retrieve all <header> elements:
  document.querySelectorAll('header')
    // using NodeList.prototype.forEach() to iterate over that NodeList:
    .forEach(
      // passing a reference to the current <header> of the NodeList to
      // the Arrow function; and within the function binding the
      // playAudio() function (note the deliberate lack of parentheses)
      // as the event-handler for the 'mouseover' event:
      (headerElement) => headerElement.addEventListener('mouseover', playAudio))
});
<header class="card" id="play_1">
  <audio>
    <source src="/voices/sound1">
  </audio>
</header>

<header class="card" id="play_2">
  <audio>
    <source src="/voices/sound2">
  </audio>
</header>

<header class="card" id="play_3">
  <audio>
    <source src="/voices/sound3">
  </audio>
</header>

参考文献: