JS将鼠标悬停在一个项目上以进行另一动作

时间:2019-01-24 18:39:41

标签: javascript

我有一个简单的文本按钮,旁边有一个箭头图像。我希望当有人将鼠标悬停在按钮上时箭头图像会移动。

我目前正在使用JS'document.getElementById ...'在一个实例中进行此操作,但是我的网站上有多个按钮希望具有相同的行为。我首先想到的是使用类而不是id,并使用相同的功能。

无论出于何种原因,document.getElementsByClassName都不起作用-即使在一个实例中也是如此。

这是一个更简单的版本来演示-在Codepen上查看:https://codepen.io/sdorr/pen/JxYNpg

HTML

<HTML>
    <a href="#" class="button" onmouseover="move()" onmouseout="moveBack()">hover over me</a>

    <div id="block"></div>

    <a href="#" class="button" onmouseover="moveAlt()" onmouseout="moveBackAlt()">hover over me</a>

    <div class="block"></div>

CSS

* {
  margin: 0;
  padding: 0;
}

.button {
  color: #000000;
  text-decoration: none;
  background-color: cyan;
  margin: 0;
  display: block;
  width: 300px;
  padding: 20px;
  text-align: center;
}

#block {
  width: 30px;
  height: 30px;
  background-color: red;
}

.block {
  width: 30px;
  height: 30px;
  background-color: green;
}

JS

function move() {
    document.getElementById("block").style.marginLeft = "35px";
}

function moveBack() {
    document.getElementById("block").style.marginLeft = "0px";
}

function moveAlt() {
    document.getElementsByClassName("block").style.marginLeft = 
"35px";
}

function moveBackAlt() {
    document.getElementsByClassName("block").style.marginLeft = 
"0px";
}

首先,为什么类的行为不起作用,但id可以正常工作?

第二,一个类是否可以解决此问题,并且可以在具有相同两个功能(onmouseover / onmouseout)的所有按钮上进行扩展?

如果没有,关于解决方案有什么想法吗?我目前有一个使用jQuery的解决方案,该解决方案确实有效,但是将鼠标悬停在一个按钮上时,所有箭头图像都会在网站上移动。我不必介意这种行为,因为一次只能看到一个按钮-但是我正在尝试学习JS并用自己的解决方案解决问题!

2 个答案:

答案 0 :(得分:0)

非常感谢您渴望自己学习而不依赖预制解决方案的愿望。保持这种精神,你会去的地方!

对于getElementsById,我们知道这应该适用于一个元素,因为该函数返回单个元素。

但是,getElementsByClassName返回什么? (请参阅:https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName

它返回一个HTMLCollection,您可以循环访问它来更改单个元素的style

因此,要使其与JavaScript一起使用,您需要编写一个函数,该函数将能够识别要移动的特定div.block。但是,这使您回到起点,需要一些特定的标识符,例如iddataset值才能传递给函数。

或者,根据您提供的HTML结构,您可以在被点击的nextElementSibling上寻找a。但是我会设置一个eventListener而不是将JS函数作为值添加到onmouseenter属性中。

const btns = document.getElementsByTagName('a');
/*** UPDATE forEach is a NodeList method, and will fail on HTMLCollection ***/
/* this fails -> Sorry! ~~btns.forEach(button=>{~~
/* the following will work
/**********/
for (let i = 0; i < btns.length; i++){
    btns[i].addEventListener('mouseenter', function(e) {
        //we pass e to the function to get the event and to be able to access this
        const block = this.nextElementSibling;
        block.style.marginLeft = "35px";
    })

    btns[i].addEventListener('mouseleave', function(e) {
        const block = this.nextElementSibling;
        block.style.marginLeft = "0";
    })
}

但是有兄弟姐妹,只有CSS解决方案。

如果我们只是来回移动,我们可以将Adjacent Sibling Selector:hover状态选择器结合使用,并且不需要JavaScript。

.button:hover+.block {
    margin-left: 35px;
}

查看下方的片段

* {
  margin: 0;
  padding: 0;
}

.button {
  color: #000000;
  text-decoration: none;
  background-color: cyan;
  margin: 0;
  display: block;
  width: 300px;
  padding: 20px;
  text-align: center;
}

.block {
  width: 30px;
  height: 30px;
  background-color: green;
}

.button:hover+.block {
    margin-left: 35px;
}
<a href="#" class="button">hover over me</a>

<div class="block"></div>


<a href="#" class="button">hover over me</a>

<div class="block"></div>

答案 1 :(得分:0)

如Vecta所述,getElementsByClassName返回类似数组的形式。您需要执行以下操作才能获取第一个元素:

function moveAlt() {
    document.getElementsByClassName("block")[0].style.marginLeft = "35px";
}

function moveBackAlt() {
    document.getElementsByClassName("block")[0].style.marginLeft = "0px";
}

但是,更好的解决方案可能是使用document.querySelector,其操作类似于jQuery的$()语法:

function moveAlt() {
    document.querySelector(".block").style.marginLeft = "35px";
}

function moveBackAlt() {
    document.querySelector(".block").style.marginLeft = "0px";
}