JavaScript - 遍历所有标签,为每个标签添加一个onclick

时间:2012-04-12 23:22:44

标签: javascript

我有一个指向图像的链接列表,以及一个带有(图像的)URL的js函数,并在调用该函数时将该图像放在页面上。

我最初在每个a中添加了内联onlick =“showPic(this.getAttribute('href'))”,但我想将内联js分开。这是我的函数,用于在页面加载时为每个标记添加onclick:

function prepareLinks(){
var links = document.getElementsByTagName('a');
for(var i=0; i<links.length; i++){
    var thisLink = links[i];
    var source = thisLink.getAttribute('href'); 
    if(thisLink.getAttribute('class') == 'imgLink'){
        thisLink.onclick = function(){
            showPic(source);
            return false;
        }
    }
}
}

function showPic(source){
var placeholder = document.getElementById('placeholder');
placeholder.setAttribute('src',source);
}

window.onload = prepareLinks();

...但每次调用showPic时,source var都是最后一个图像的href。如何让每个链接都有正确的onclick?

4 个答案:

答案 0 :(得分:4)

JavaScript没有块范围,因此关闭的变量最终会成为最后分配给它的内容。您可以通过将其包装在另一个闭包中来解决此问题:

function prepareLinks() {
    var links = document.getElementsByTagName('a');
    for(var i = 0; i < links.length; i++) {
        var thisLink = links[i];
        var source = thisLink.getAttribute('href'); 
        if(thisLink.getAttribute('class') == 'imgLink') {
            thisLink.onclick = (function(source) {
                return function() {
                    showPic(source);
                    return false;
                };
            })(source);
        }
    }
}

当然,您可以更简单地使用this

function prepareLinks() {
    var links = document.getElementsByTagName('a');

    for(var i = 0; i < links.length; i++) {
        var thisLink = links[i];

        if(thisLink.getAttribute('class') == 'imgLink') {
            thisLink.onclick = function() {
                showPic(this.href);
                return false;
            };
        }
    }
}

我相信这会破坏与IE5或IE6的兼容性,但希望你不关心其中任何一个=)

答案 1 :(得分:2)

Minitech的答案应该解决您的问题,即所有onclick处理程序共享source变量

您执行此操作的方式非常浪费,无需为每个链接设置单独的处理程序。此外,如果动态添加任何链接,它将无法工作。事件授权是可行的方式。

function interceptLinks() {
   // Bad way to set onclick (use a library)
   document.onclick = function() {
     if (this.tagName.toUpperCase() != 'A' ) {
       return;
     }
     // Bad way to check if it contains a class (use a library)
     if (this.getAttribute('class') == 'imgLink') {
       showPic(this.getAttribute('href'));
       return false;
     }
   }
}

答案 2 :(得分:0)

这是访问外部变量的循环内事件处理程序的古老问题。

source事件发生时,您的click变量已从范围链中拉出,到那时,由于迭代完成,它已被设置为最后一个href属性

您需要通过执行以下两项操作之一来解决问题。

最简单但许多浏览器不支持使用let,它允许您使用块范围。

let source = thisLink.getAttribute('href'); 

jsFiddle。它适用于Firefox,但不适用于Chrome。

在2038年,当我们处理year 2038 problem并且所有浏览器都已实施ES6时,这将是修复此问题的标准方法。

与所有浏览器兼容的更难以理解和实现的方法是使用诸如...之类的模式来打破闭包。

thisLink.onclick = (function(src) {
  return function(){
            showPic(src);
            return false;
        }
})(source);

jsFiddle

答案 3 :(得分:0)

感谢所有回复。结果我错误地诊断出了这个问题,对不起。实际上使用了一个新的var和annon。函数在每个循环迭代上添加一个onclick工作(传递的href是正确的)。它没有工作,因为我通过“imgLink”类获取了a-tags,当我删除了内联onclick处理程序时,我从HTML中删除了它(我现在在父节点上获取它们的ID)。我还需要使用“return!showPic(this.href);”单击时停止正常关注的链接。

工作代码:

function showPic(source){
var placeholder = document.getElementById('placeholder');
placeholder.setAttribute('src',source);
return true;
}

function prepareLinks() {
if(!document.getElementById('imgLinks')){ return false; };
var galLinks = document.getElementById('imgLinks');
var links = galLinks.getElementsByTagName('a');
for(var i=0; i<links.length; i++) {
    var thisLink = links[i];
    thisLink.onclick = function() {
        return !showPic(this.href);
    };
}
}

window.onload = function(){
prepareLinks();
}
相关问题