javascript函数中的特定行不起作用

时间:2011-03-13 05:36:13

标签: javascript jquery dom

我今天晚上才开始使用此功能。然而,在经过一些小的编辑后,if / else的另一部分将被删除,其中一部分神奇地停止了工作。

json请求的回调函数中的四个for循环都执行,但实际上没有进行任何DOM操作。我已经三次检查是否存在适当的DOM元素。警报将在所有警报中触发。只是jQuery行失败了。

我已尝试将相关变量放入控制台并手动迭代数字以模拟循环。这很好用。我还使用警报来显示循环中变量的顺序,这些都可以正常运行。

我很困惑。

function drawPreview() {
    var $preview = $('#preview');
    $preview.remove();
    $('#general_preview').remove();
    try {
        activecell.location;
    }
    catch (error) {
        $('#active_cell').clone().attr('id','general_preview').appendTo('#win_preview');
        return;
    }
    if (activecell.location.match(/^\d+_\d+$/)!==null) {
        var x = parseInt(activecell.location.slice(0,activecell.location.indexOf("_")));
        var y = parseInt(activecell.location.slice(activecell.location.indexOf("_")+1));
        var area = "x"+activearea.join("x")+"x";
        $('#win_preview').append($('<div id="preview"><div><div></div><div></div><div></div></div><div><div></div><div></div><div></div></div><div><div></div><div></div><div></div></div></div>'));
        var i = y-1;
        var j = x-1;
        function loadCell() {
            var exp = new RegExp("x"+i+"_"+j+"x","g");
            if (area.match(exp)) {
                if (i==y&&j==x) {
                    $('#active_cell').clone().children().unwrap().appendTo($preview.children().eq(1).children().eq(1));
                    ++j;
                    loadCell();
                }
                else {
                    var jqxhr = $.getJSON('data/areas/'+$('#select_area').val()+'/'+x+"_"+y+'.json', function(data) {
                        var tmp = data;
                        for (var l=0; l<9; ++l) {
                            $preview.children().eq(i-y+1).children().eq(j-x+1).append('<div></div>');
                        }
                        for (var l=0; l<9; ++l) {
                            $preview.children().eq(i-y+1).children().eq(j-x+1).children().append('<div></div>');
                        }
                        for (var l = 0; l < 9; ++l) {
                            for (var m = 0; m < 9; ++m) {
                                $preview.children().eq(i-y+1).children().eq(j-x+1).children().eq(l).children().eq(m).attr("style","background: #"+tmp.p.c[tmp.c[l][m]-1]+" url(textures/terrain/"+tmp.p.t[tmp.t[l][m]-1]+".png) bottom center no-repeat");
                            }
                        }
                        if (i==y+1&&j==x+1) {
                            return;
                        }
                        else if (j==x+1) {
                            ++i;
                            j = x-1;
                            loadCell();
                        }
                        else {
                            ++j;
                            loadCell();
                        }
                    })
                        .error(function() { alert("There was an error loading the data. The data may be invalid or you may be looking for a file that does not exist."); })
                }
            }
            else {
                if (i==y+1&&j==x+1) {
                    return;
                }
                else if (j==x+1) {
                    ++i;
                    j = x-1;
                    loadCell();
                }
                else {
                    ++j;
                    loadCell();
                }
            }
        }
        loadCell();
    }
}

2 个答案:

答案 0 :(得分:3)

一开始,你称之为

var $preview = $('#preview');

然后,在第一个if分支中:

$('#win_preview').append($('<div id="preview"><div...

这是好的,但在回调中,通过

$preview.children().eq(i-y+1).children()....

您正在尝试访问不再存在的元素。您需要获得刚刚添加的#preview的新引用。也许在那个有<div></div>吨附加的那一行之后:)

编辑:

另外,我建议你使用一些类选择器,而不是依赖于精确的DOM树结构(使用大量的eq())。如果你想以某种方式更新标记,它可能在将来节省你一些时间。此外,一旦你进入这个样式,你可以将这些选择器作为CSS样式副作用,所以为什么不立即使用它们。

另一件事:如果代码变得复杂且可读性不高,您可以尝试帮助自己进行一些调试:

for (var l=0; l<9; ++l) {
    $preview.children().eq(i-y+1).children().eq(j-x+1).append('<div></div>');
}

也可以写成

var targetParent = $preview.children().eq(i-y+1).children().eq(j-x+1);
console.log(targetParent);
for (var l=0; l<9; ++l) {
    targetParent.append('<div></div>');
}

你会在控制台中看到(假设是firefox + firebug调试),你正准备追加到哪里。这样做的另一个好处是它可以帮助您优化代码 - 您只需要追加目标一次,然后在循环中追加它。以前的变体既可以获得目标,也可以在循环中追加。

答案 1 :(得分:0)

我已经做了一个相当标准的重构来减少嵌套if语句的数量(这是逻辑错误和混乱的常见滋生地)。我鼓励你发布一些测试数据(如果你愿意,还有一个夹具),你希望这些数据能够真正发挥作用。一段有效的dom和一个单元数据样本应该足够了。

function drawPreview() {
    var $preview = $('#preview'),
        x, y, area, i, j;

    function repeat( text, count ){
        var i=0, out = '';
        for( ; i++ < count ; ) {
            out += text;
        }
        return out;
    }

    $preview.remove();
    $('#general_preview').remove();
    try {
        activecell.location;
    }
    catch (error) {
        $('#active_cell').clone().attr('id','general_preview').appendTo('#win_preview');
        return;
    }
    if (activecell.location.match(/^\d+_\d+$/) === null ){
        return;
    }
    x = parseInt(activecell.location.slice(0,activecell.location.indexOf("_")), 10);
    y = parseInt(activecell.location.slice(activecell.location.indexOf("_")+1), 10);
    area = "x"+activearea.join("x")+"x";
    $('#win_preview').append($('<div id="preview"><div>' + repeat('<div>' + repeat('<div></div>', 4) + '</div>', 3) + '</div></div>'));
    i = y-1;
    j = x-1;
    function loadCell() {
        var exp = new RegExp("x"+i+"_"+j+"x","g"),
            sel_area;

        if (! area.match(exp)){
            if (i==y+1&&j==x+1) {
                return;
            }
            else if (j==x+1) {
                ++i;
                j = x-1;
                loadCell();
            }
            else {
                ++j;
                loadCell();
            }
            return;
        }
        if (i==y&&j==x) {
            $('#active_cell').clone()
                .children()
                .unwrap()
                .appendTo($preview.children()
                                .eq(1)
                                .children()
                                .eq(1)
                );
            ++j;
            loadCell();
            return;
        }
        var sel_area = $('#select_area').val();
        var jqxhr = $.getJSON('data/areas/'+ sel_area +'/'+x+"_"+y+'.json', function(data) {
            var tmp = data, l = 0, m = 0;
            for ( l=0; l<9; ++l ) {
                $preview.children()
                        .eq(i-y+1)
                        .children()
                        .eq(j-x+1)
                        .append('<div></div>');
            }
            for ( l=0; l<9; ++l) {
                $preview.children()
                        .eq(i-y+1)
                        .children()
                        .eq(j-x+1)
                        .children()
                        .append('<div></div>');
            }
            for ( l = 0; l < 9; ++l) {
                for ( m = 0; m < 9; ++m) {
                    $preview.children()
                            .eq(i-y+1)
                            .children()
                            .eq(j-x+1)
                            .children()
                            .eq(l)
                            .children()
                            .eq(m)
                            .css({background: "#"+tmp.p.c[tmp.c[l][m]-1]+" url(textures/terrain/"+tmp.p.t[tmp.t[l][m]-1]+".png) bottom center no-repeat"});
                }
            }
            if (i==y+1&&j==x+1) {
                return;
            }
            else if (j==x+1) {
                ++i;
                j = x-1;
                loadCell();
                return;
            }
            ++j;
            loadCell();
            return;
        }).error(function() { alert("There was an error loading the data. The data may be invalid or you may be looking for a file that does not exist."); });
    }
    loadCell();
}