javascript - index.js:66 未捕获的类型错误:无法在 HTMLDivElement 处读取未定义的属性(读取“innerText”)。(index.js:66)
问题描述
我试图创建一个鼓槌网站作为#javascript30 挑战的一部分,但我收到以下错误:
index.js:66 未捕获的类型错误:无法在 HTMLDivElement 处读取未定义的属性(读取“innerText”)。(index.js:66)
function playAudio(key) {
switch (key) {
case 'a':
case 'A':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 's':
case 'S':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 'd':
case 'D':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 'f':
case 'F':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 'g':
case 'G':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 'h':
case 'H':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 'j':
case 'J':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 'k':
case 'K':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
case 'l':
case 'L':
var clap = new Audio("sounds/clap.wav");
clap.play();
break;
default:
console.log(key);
}
}
// To produce sound when the drum is CLICKED
for (var i = 0; i < document.querySelectorAll(".key").length; ++i) {
// console.log(i);
document.querySelectorAll(".key")[i].addEventListener("click", function() {
var keyPress = document.getElementsByTagName("kbd")[i].innerText; // !!problem in this line!!
playAudio(keyPress);
buttonAnimation(keyPress);
});
}
// To produce sound when the drum key is pressed
document.addEventListener("keypress", function(event) { //call back funtion passes back evt obj
playAudio(event.key);
buttonAnimation(event.key);
});
function buttonAnimation(currentKey) {
try {
document.querySelector("." + currentKey.toUpperCase()).classList.add("playing");
setTimeout(function() {
document.querySelector("." + currentKey.toUpperCase()).classList.remove("playing");
}, 100);
} catch (err) {
console.log(err.message);
}
}
for (var i = 0; i < document.querySelectorAll(".key").length; ++i) {
// console.log(i);
document.querySelectorAll(".key")[i].addEventListener("click", function() {
var keyPress = document.getElementsByTagName("kbd")[i].innerText; // !!problem in this line!!
playAudio(keyPress);
buttonAnimation(keyPress);
});
}
<div class="keys">
<div class="A key">
<kbd>A</kbd>
<span class="sound">clap</span>
</div>
<div class="S key">
<kbd>S</kbd>
<span class="sound">hihat</span>
</div>
<div class="D key">
<kbd>D</kbd>
<span class="sound">kick</span>
</div>
<div class="F key">
<kbd>F</kbd>
<span class="sound">openhat</span>
</div>
<div class="G key">
<kbd>G</kbd>
<span class="sound">boom</span>
</div>
<div class="H key">
<kbd>H</kbd>
<span class="sound">ride</span>
</div>
<div class="J key">
<kbd>J</kbd>
<span class="sound">snare</span>
</div>
<div class="K key">
<kbd>K</kbd>
<span class="sound">tom</span>
</div>
<div class="L key">
<kbd>L</kbd>
<span class="sound">tink</span>
</div>
</div>
解决方案
我认为问题在于尝试迭代querySelectorAll
两次给出的节点列表,将所有这些侦听器添加到循环中的元素,然后尝试kbd
使用该索引获取元素。
不是附加所有这些侦听器,而是使用事件委托并将一个侦听器附加到.keys
元素。
然后,您可以找到前一个标签的文本(请注意,由于 HTML 中的空白,我们在此处使用了 previousSibling 两次,并将其记录下来。
这是您的代码的简化示例。
function playAudio(key) {
console.log(key);
}
const keys = document.querySelector('.keys');
keys.addEventListener('click', handleClick, false);
function handleClick(e) {
const kbd = e.target.previousSibling.previousSibling;
const key = kbd.textContent;
playAudio(key);
}
.key { cursor: pointer; }
.key:hover { color: red; }
<div class="keys">
<div class="A key">
<kbd>A</kbd>
<span class="sound">clap</span>
</div>
<div class="S key">
<kbd>S</kbd>
<span class="sound">hihat</span>
</div>
<div class="D key">
<kbd>D</kbd>
<span class="sound">kick</span>
</div>
<div class="F key">
<kbd>F</kbd>
<span class="sound">openhat</span>
</div>
<div class="G key">
<kbd>G</kbd>
<span class="sound">boom</span>
</div>
</div>