我的Javascript有一些bug

时间:2014-12-01 05:42:25

标签: javascript html

我写了一个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>

3 个答案:

答案 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")..
  ...
}

函数()中的indexfree-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';
    }
});

这是一个小提琴演示:

http://jsfiddle.net/z3xkf9fs/

当每个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;
                };
            }
};