首页 > js使用for修改a标签内容只有一个被修改

js使用for修改a标签内容只有一个被修改

我希望页面中的所有a标签都被修改,但是打开页面总是最后一个标签被修改,而且有时是第一个标签的内容。

<!DOCTYPE html>
<meta charset="UTF-8">
<div id="content">http://www.xiami.com/song/1770607143<br>http://www.xiami.com/song/1999582</div>
<style>
.music{line-height:1.4;padding:.3em .8em .3em .3em;border-radius:.3em;color:#35D;display:inline-block;text-decoration:none!important}
.music:hover{background:rgba(80,190,255,.1)}
.music:after{margin-left:.5em;font-style:normal;color:#999;content:'▷'}
.music.play{background:rgba(80,190,255,.1)}
.music.play:after{content:'| |'}
.music.pause:after{content:'▷'}
</style>
<script>
$ = function(i) {
    return document.querySelector(i)
};
$.S = function(i) {
    return document.querySelectorAll(i)
};
$.x = function(i, p, f) {
    var x = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
    x.open(p ? 'POST' : 'GET', i, 1);
    x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    x.send(p || '');
    if (f) x.onreadystatechange = f;
}
String.prototype.enHtml = function() {
    return this.replace(/(^\s*)|(\s*$)/g, '').replace(/(http\:\/\/|)(ww[0-9]{1}\.sinaimg\.cn\/)(?:[\w]{4,10})(\/[\w]{16,32}\.)(gif|jpg|jpeg|png)/g, "http://$2bmiddle$3$4").replace(/http:\/\/www\.xiami\.com\/song\/([0-9]{5,12})[\?\w\.\=]*/g, '<a href="//www.xiami.com/song/$1" target="_blank" class="music">http://www.xiami.com/song/$1</a>').replace(/(http\:\/\/[0-9A-Za-z\/.#&!?%:;=_]+\.)(gif|jpg|jpeg|png)/g, "<img src=\"$1$2\">").replace(/(^|[^\"\'\]>])(http|ftp|mms|rstp|news|https|telnet)\:\/\/([0-9A-Za-z\/.#&!?%:;=\-_]+)/g, '$1<a href="$2://$3" rel="external nofollow noreferer" class="link" target="_blank">$2://$3</a>').replace(/(@)([\u4e00-\u9fa5\u0800-\u4e00A-Za-z0-9\-_]{2,32})/ig, "<span class=\"at\">$1$2</span>").replace(/\n/g, '<br>')
};
var music = function(g, f) {
        if (!$.Audio) {
            $.Audio = new Audio()
        }
        $.Audio.addEventListener("ended", function() {
            if ($(".music.play")) {
                $(".music.play").className = "music"
            }
        }, false);
        var c = function() {
                for (var p = $.S(".music"), k, n, o, h = p.length, m = 0; m < h; m++) {
                    k = p[m];
                    o = k.href.match(/[0-9]{5,12}$/) * 1;
                    if (k.onclick) {
                        continue
                    }
                    $.x('http://xmplayer.applinzi.com/?id=' + o, 0, function() {
                        if (this.readyState == 4 && this.status == 200) {
                            var json = eval('(' + this.responseText + ')');
                            name = json.name, artist = json.artist, url = json.url;
                            k.innerHTML = name + ' - ' + artist;
                            k.onclick = function() {
                                if (this.className == "music") {
                                    this.className = "music play";
                                    $.Audio.src = url;
                                    $.Audio.play()
                                } else {
                                    if (this.className == "music play") {
                                        this.className = "music pause";
                                        $.Audio.pause()
                                    } else {
                                        this.className = "music play";
                                        $.Audio.play()
                                    }
                                }
                                return false
                            }
                        }
                    })
                }
            }
        c();
    }
$('#content').innerHTML = $('#content').innerHTML.enHtml();
music();
</script>

本地测试结果是:


这个问题应该是属于JS的闭包问题,问题点在下面的代码部分:

                for (var p = $.S(".music"), k, n, o, h = p.length, m = 0; m < h; m++) {
                    k = p[m];
                    ...
                    $.x('http://xmplayer.applinzi.com/?id=' + o, 0, function() {
                        if (this.readyState == 4 && this.status == 200) {
                            ...
                            k.innerHTML = name + ' - ' + artist;
                            ...
                        }
                    })
                }

注意,在for循环中,k是遍历所有节点的,但是$.x()函数实际上是一个异步的HTTP请求,那么在HTTP请求完成的时候,k的值已经遍历到最后一个节点。这个可以通过添加下述打印来确认的:

k.innerHTML = name + ' - ' + artist;
console.log(k, json)

从运行结果上可以看到,json的值是正确的,但是k的值总是最后一个节点。

我的修改方法如下:

  1. $.x函数中增加参数k,并且在x.onreadystatechang回调中讲参数k再传回给回调函数

$.x = function(i, p, f, k) {
    var x = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
    x.open(p ? 'POST' : 'GET', i, 1);
    x.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    x.send(p || '');
    if (f) x.onreadystatechange = function(){
       f(this, k);
    };
}
  1. 在回调函数中使用这个传入的参数,而不是用局部变量

                    $.x('http://xmplayer.applinzi.com/?id=' + o, 0, function(xmlhttp, kk) {
                        if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                            ...
                            kk.innerHTML = name + ' - ' + artist;
                            kk.onclick = function() {
                                ...
                            }
                        }
                    }, k)

测试,修改后可以正常显示。

【热门文章】
【热门文章】