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>
参考文献:
我想让这段代码符合 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>
参考文献: