我写了一个javascript,其中我正在使用循环。 我想在div标签上的mouseover和mouseout事件上显示和隐藏表格。所有div都命名为info1,info2,.... info6,要显示的表命名为table12,table22,.... table62,要隐藏的表命名为table11,table21,... table61 ... 。 我有7个表,其中我使用6来使用此功能。 所以我编写了一个代码,但每当我将鼠标指向任何div时,它都会改变第7个表的显示属性。 以下是我的代码。请指出我的错误。
<script type='text/javascript'>
window.onload = function() {
for (var index = 1; index<= 6; index++){
document.getElementById("info" + index).onmouseover = function() {
document.getElementById ("table" + index + "1").style.display = "none";
document.getElementById ("table" + index + "2").style.display = "block";
return false;
};
document.getElementById("info" + index).onmouseout = function() {
document.getElementById ("table"+ index +"1").style.display = "block";
document.getElementById ("table"+ index +"2").style.display = "none";
return false;
};
}
};
</script>
答案 0 :(得分:3)
啊哈,我想这是一个关闭问题。 你要做的是:
for (var index = 1; index <=6 ; ++index) {
document.getElementById('info' + index).addEventListener('mouseover', (function(i) { return function() {
document.getElementById('table' + i + "1").style.display = 'none';
}}(index)));
}
我会尝试解释一下,在你的代码中,
for(var index=1 ..) {
document..onmouseover = function() { document.getElementById ("table" + index + "1")..
...
}
函数()中的index
是free-variable
,(在父作用域中定义并可在子作用域中访问),它创建了一个闭包,能够访问作用域本地的其他变量它创建于。
您正在传递对变量的引用,而不是存储在变量中的值。迭代迭代的i变量的最后一个和实际值实际上是整数
Fiddle用于演示。
答案 1 :(得分:1)
正如其他人所说,这是一个封闭问题。一个非常简单的解释是变量index
被所有onmouseover
处理程序引用。因此,在最后的循环迭代中,设置index
,然后由所有处理程序引用。
解决此问题的最简单方法是将处理程序包装在自执行函数中。这是因为function scope
。通过在每次迭代中传递index
作为参数,可以将范围限制为该函数执行。这里有其他答案可以解决这个问题,因此我不会花太多时间在上面。
(这是您在评论中链接到的更新小提琴,有效:http://jsfiddle.net/k83wuwz5/1/)
和JS(用于文档)
for (var index = 1; index<= 5; index++){
document.getElementById("info" + index).onmouseover = (function(index) {
return function() {
document.getElementById ("table" + index + "1").style.display = "none";
document.getElementById ("table" + index + "2").style.display = "block";
}
})(index);
document.getElementById("info" + index).onmouseout = (function(index) {
return function() {
document.getElementById ("table"+ index +"1").style.display = "block";
document.getElementById ("table"+ index +"2").style.display = "none";
}
})(index);
}
相反,让我们谈谈解决这个问题的其他一些方法:委托,简单的CSS(可能),以及两者的组合!
首先delegation
(因为这是一个JS问题!) - 让我们说我们在这里有这个标记(只是猜测,因为我没有看到你的实际标记):
<div id='container'>
<!-- Info DIVS -->
<div data-idx="1">Info 1</div>
<div data-idx="2">Info 2</div>
<div data-idx="3">Info 3</div>
<!-- Info Tables -->
<table><tr><td>table 1</td></tr></table>
<table><tr><td>table 2</td></tr></table>
<table><tr><td>table 3</td></tr></table>
<div>
如果,而不是在单个信息div级别监听鼠标悬停,我们说“嘿,containing
div?当您的子元素发生mouseover
时,做一些事情!”
让我们看看它的外观:
var container = document.getElementById('container');
var tables = document.getElementsByTagName('table');
var currentlyVisible = null;
container.addEventListener('mouseover', function(e) {
var idx;
if (e.target.hasAttribute('data-idx')) {
if (currentlyVisible) {
currentlyVisible.style.display = 'none';
}
idx = parseInt(e.target.getAttribute('data-idx'), 10) - 1
currentlyVisible = tables[idx];
currentlyVisible.style.display = 'block';
}
});
container.addEventListener('mouseout', function(e) {
if (currentlyVisible) {
currentlyVisible.style.display = 'none';
}
});
这是一个小提琴演示:
当每个div上发生鼠标悬停时,将通过事件冒泡“通知”父容器。诸如“target
”(或source element
)之类的信息与事件对象一起传递,我们可以参考该事件对象。在上面的代码中,我们的info div是相当基本的(它只是文本节点),但如果你有包含元素(比如一个span),你需要循环(或爬上DOM树)来找到封闭的信息div到获取索引(否则,目标将是封闭的span / div / etc)。
(这就是为什么jQuery和其他人如此受欢迎 - 使用事件委派,所有这些都是由图书馆为你完成的。)
一旦我们知道了info div,我们就会查询该属性并使用它。还有其他方法可以解决这个问题(你可以确定有多少个信息div并确定索引的方式 - 或者使用一个类),但我选择了data-attributes
。
最后,在mouseout
上,我们检查是否设置了currentlyVisible
变量,如果是,我们会隐藏元素。
这是非常简单的委托,但CSS怎么样?
好吧,如果浏览器支持不是主要问题(基本上是旧版本的IE),那么CSS就是这样的方式!再次,让我们使用我们的基本标记,但更新了一些class
属性:
<div id='container'>
CSS ONLY!
<br />
<!-- Info DIVS -->
<div class="info info1">Info 1</div>
<div class="info info2">Info 2</div>
<div class="info info3">Info 3</div>
<!-- Info Tables -->
<table class="table1"><tr><td>Table 1</td></tr></table>
<table class="table2"><tr><td>Table 2</td></tr></table>
<table class="table3"><tr><td>Table 3</td></tr></table>
<div>
现在我们的CSS:
table {
display: none;
}
div > .info1:hover ~ .table1,
div > .info2:hover ~ .table2,
div > .info3:hover ~ .table3 {
display: table;
}
div > div {
cursor: pointer;
display: inline-block;
margin: 10px;
}
就是这样!没有JS需要显示/隐藏表。公平警告,~
选择器不受支持。同样,正如我上面提到的,如果你可以修改标记结构(因此表是嵌套的),CSS就会大大简化(只是嵌套的div选择器)。此外,如果你的标记是如此混乱,这可能甚至不起作用。
无论如何,这是一个小提琴演示:http://jsfiddle.net/z3xkf9fs/1/
最后,你可以使用这个的组合(比如你的标记可以阻止你做纯CSS)。
让我们说我们的标记看起来像这样:
<div id='container'>
<!-- Info DIVS -->
<div data-idx="1">Info 1</div>
<div data-idx="2">Info 2</div>
<div data-idx="3">Info 3</div>
<!-- Info Tables -->
<table class="t1"><tr><td>table 1</td></tr></table>
<table class="t2"><tr><td>table 2</td></tr></table>
<table class="t3"><tr><td>table 3</td></tr></table>
<div>
我们的JS看起来像这样:
(function(){
var container = document.getElementById('container');
var tables = document.getElementsByTagName('table');
var currentlyVisible = null;
container.addEventListener('mouseover', function(e) {
var idx;
if (e.target.hasAttribute('data-idx')) {
container.setAttribute('class', 'idx' + e.target.getAttribute('data-idx'));
}
});
container.addEventListener('mouseout', function(e) {
container.removeAttribute('class');
});
}())
我们的CSS看起来像这样:
table {
display: none;
}
div > div {
cursor: pointer;
display: inline-block;
margin: 10px;
}
.idx1 .t1,
.idx2 .t2,
.idx3 .t3 {
display: table;
}
祝你好运!
答案 2 :(得分:0)
我打算建议把变量放在for循环函数之外:
window.onload = function() {
var index = 1;
for ( index<= 6; index++){
document.getElementById("info" + index).onmouseover = function() {
document.getElementById ("table" + index + "1").style.display = "none";
document.getElementById ("table" + index + "2").style.display = "block";
return false;
};
document.getElementById("info" + index).onmouseout = function() {
document.getElementById ("table"+ index +"1").style.display = "block";
document.getElementById ("table"+ index +"2").style.display = "none";
return false;
};
}
};