【问题标题】:adding event listeners with list.forEach() - only last list item changes使用 list.forEach() 添加事件侦听器 - 仅最后一个列表项更改
【发布时间】:2020-11-26 16:23:16
【问题描述】:

我是网页设计(和编码)的新手,今天下午我遇到了一个我无法单独解决的问题。我希望你们中的一个可以帮助我。

我想创建文本元素,当用户将鼠标悬停在它上面时变为绿色,当鼠标再次熄灭时变为红色。 (稍后,当鼠标悬停在特定对象上时,音频文件将开始播放。) 运行代码时,您可以看到只有最后一个元素变为红色,当鼠标悬停在其他元素上时也是如此。我的 (Javascript) 代码有什么问题?

const elements = [
    {title: 'Element1'},
    {title: 'Element2'},
    {title: 'Element3'},
    {title: 'Element4'},
    {title: 'Element5'}
];

window.onload = () => {
    elements.forEach(element => {
        title = document.getElementById(element.title);
        //add event listeners
        title.addEventListener("mouseover", handleMouseOver = () => {
            mouseOver(title);
        });
        title.addEventListener("mouseout", handleMouseOut = () => {
            mouseOut(title);
        });
    });
};

//play soundfiles
const mouseOver = (title) => {
    title.style.backgroundColor = "red";
};
const mouseOut = (title) => {
    title.style.backgroundColor = "#4CAF50";
};
body {
    margin:0;
          margin-left:0em;
          padding:0;
          overflow: hidden;
      }
      canvas {
          margin:auto;
      }

.compositions {
    display: inline-block;
    align-items: center;
    font-style: arial;
    font-size: 17px;
    list-style-type: none;
    text-align: center;
    margin-top: 5em;
}
.compositions p {
    margin-bottom: 0.8em;
    margin:0em 0.8em 1em 1em;
    display: inline-block;
}

.compositions input {
    background-color: #4CAF50; /* Green */
    border: none;
    border-radius:50px;
    color: white;
    padding: 8px 20px;
    margin-left: 10px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-style: arial;
    font-size: 12px;
}

.compositions p:hover{
    font-weight: bold;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>InteractiveWebsite</title>

    <script src="../libraries/p5.js"></script>
    <script src="../libraries/p5.dom.js"></script>
    <script src="../libraries/p5.sound.js"></script>
    <!--script src="../libraries/Tone.js"></script-->
    <!--CreateJS libraries-->
    <script src="../libraries/soundjs.min.js"></script>
    <script src="../libraries/cordovaaudioplugin.min.js"></script>
    <script src="../libraries/flashaudioplugin.min.js"></script>
    <script src="../libraries/preloadjs.min.js"></script>
    <!--Own javascript files-->

    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <main>
        <div class="compositions">
            <p id=Element1>Element 1</p><br>
            <p id=Element2>Element 2</p><br>
            <p id=Element3>Element 3</p><br>
            <p id=Element4>Element 4</p><br>
            <p id=Element5>Element 5</p><br>
        </div>
    </main>
    <script src="sketch.js"></script>
    <noscript>Sorry, your browser does not support JavaScript!</noscript>
</body>
</html>

我研究了另外两个主题(herehere),但它们似乎不适用于我的情况。

提前致谢, 芥末整形器

【问题讨论】:

  • title 是一个全局变量,因为它没有被声明,所以首先声明它:let title = ...
  • 顺便说一句,你为什么要为每个事件使用 2 个函数,只需将 mouseOvermouseOut 设为常规函数(例如 const mouseOver = function() { this.style... }),这样你就可以在里面使用 this,然后通过直接指向addEventListener 就像这样:title.addEventListener("mouseover", mouseOver);this 将引用触发事件的元素。对mouseOut做同样的事情
  • 不幸的是,声明变量并没有解决也没有改变代码。会不会有其他问题或解决方案?感谢您的第二条评论,这确实更合乎逻辑。
  • 声明变量确实可以解决问题,我刚刚尝试过,它可以工作。你能再检查一下吗? title = document.getElementById(element.title); 应该变成 let title = document.getElementById(element.title);
  • 啊,你是对的!对不起,我检查了我的扩展代码,它没有解决问题。但是,其他问题一定是问题所在。谢谢!

标签: javascript event-handling interactive


【解决方案1】:

你面临一个闭包问题,标题没有声明

window.onload = () => {
    elements.forEach(element => {
        title = document.getElementById(element.title);
        //add event listeners
        title.addEventListener("mouseover", handleMouseOver = () => {
            mouseOver(title);
        });
        title.addEventListener("mouseout", handleMouseOut = () => {
            mouseOut(title);
        });
    });
}

所以“默认声明”似乎在 forEach 之外。只需将其声明为 const title = document.getElementById(element.title); 即可,一切正常。

还可以在 id 属性中添加引号,例如

            <p id='Element1'>Element 1</p><br>

这不是您的错误的一部分,而只是一个小错误

版本

如您所见,它有效

const elements = [
    {title: 'Element1'},
    {title: 'Element2'},
    {title: 'Element3'},
    {title: 'Element4'},
    {title: 'Element5'}
];

window.onload = () => {
    elements.forEach(element => {
        const title = document.getElementById(element.title);
        //add event listeners
        title.addEventListener("mouseover", handleMouseOver = () => {
            mouseOver(title);
        });
        title.addEventListener("mouseout", handleMouseOut = () => {
            mouseOut(title);
        });
    });
};

//play soundfiles
const mouseOver = (title) => {
    title.style.backgroundColor = "red";
};
const mouseOut = (title) => {
    title.style.backgroundColor = "#4CAF50";
};
body {
    margin:0;
          margin-left:0em;
          padding:0;
          overflow: hidden;
      }
      canvas {
          margin:auto;
      }

.compositions {
    display: inline-block;
    align-items: center;
    font-style: arial;
    font-size: 17px;
    list-style-type: none;
    text-align: center;
    margin-top: 5em;
}
.compositions p {
    margin-bottom: 0.8em;
    margin:0em 0.8em 1em 1em;
    display: inline-block;
}

.compositions input {
    background-color: #4CAF50; /* Green */
    border: none;
    border-radius:50px;
    color: white;
    padding: 8px 20px;
    margin-left: 10px;
    text-align: center;
    text-decoration: none;
    display: inline-block;
    font-style: arial;
    font-size: 12px;
}

.compositions p:hover{
    font-weight: bold;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>InteractiveWebsite</title>

    <script src="../libraries/p5.js"></script>
    <script src="../libraries/p5.dom.js"></script>
    <script src="../libraries/p5.sound.js"></script>
    <!--script src="../libraries/Tone.js"></script-->
    <!--CreateJS libraries-->
    <script src="../libraries/soundjs.min.js"></script>
    <script src="../libraries/cordovaaudioplugin.min.js"></script>
    <script src="../libraries/flashaudioplugin.min.js"></script>
    <script src="../libraries/preloadjs.min.js"></script>
    <!--Own javascript files-->

    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
    <main>
        <div class="compositions">
            <p id='Element1'>Element 1</p><br>
            <p id='Element2'>Element 2</p><br>
            <p id='Element3'>Element 3</p><br>
            <p id='Element4'>Element 4</p><br>
            <p id='Element5'>Element 5</p><br>
        </div>
    </main>
    <script src="sketch.js"></script>
    <noscript>Sorry, your browser does not support JavaScript!</noscript>
</body>
</html>

【讨论】:

  • 亲爱的 Farvilain,感谢您的快速回答!我根据您的建议更改了代码,但是并没有解决问题。这些词一直以同样的方式表现。
  • 我添加了一个带有修正的 sn-p,你可以看到一切正常
  • 你是对的,我的错!我在我的扩展代码中工作,它没有改变,但那里肯定有其他问题。
【解决方案2】:

我知道您稍后需要播放音频文件,但是当您可能只需要solve the problem with CSS 时,这是一项非常艰巨的工作。一般来说,你不想用 JavaScript 做你可以用 CSS 做的事情。将 JavaScript 保存为 CSS 无法完成的事情。

p {
  background-color: #4CAF50;
}
p:hover {
  background-color: red;
}

【讨论】:

  • 嗨折断的食指!因为我稍后会添加更多代码——尤其是用于声音文件的代码,一旦鼠标悬停在文本对象上就会开始播放——css 不是解决方案。这个例子只是我的代码在调试过程中的简化版本。
猜你喜欢
  • 2019-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多