【问题标题】:Closure problem? - passing current value of a variable关闭问题? - 传递变量的当前值
【发布时间】:2009-11-04 01:18:34
【问题描述】:

我试图在单击动态生成的导航“节点”时传递变量的当前值。这需要只是一个整数,但它总是导致最后一个节点的值..尝试了一些不同的方法来传递值,自定义事件侦听器,设置器,但我怀疑这是一个闭包问题.. 帮助将不胜感激;-)

function callGrid():void {

    for (var i:Number = 0; i < my_total; i++) {

        var gridnode_url = my_grid[i].@gridnode;
        var news_category= my_grid[i].@category;
        var newstitle = my_grid[i].@newstitle;
        var news_content = my_grid[i]..news_content;
        var news_image = my_grid[i]..news_image;

        var gridnode_loader = new Loader();
        container_mc.addChild(gridnode_loader);
        container_mc.mouseChildren = false;
        gridnode_loader.load(new URLRequest(gridnode_url));
        gridnode_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, gridLoaded);
        gridnode_loader.name = i;

        text_container_mc = new MovieClip();
        text_container_mc.x = 0;
        text_container_mc.mouseEnabled = false;
        var textY = text_container_mc.y = (my_gridnode_height+18)*y_counter;
        addChild(text_container_mc);
        var tf:TextSplash=new TextSplash(newstitle,10,0,4 );
        container_mc.addChild(tf);
        tf.mouseEnabled = false;
        tf.height = my_gridnode_height;
        text_container_mc.addChild(tf); 
        var text_container_mc_tween = new Tween(text_container_mc, "alpha", Strong.easeIn, 0,1,0.1, true);

        gridnode_loader.x = (my_gridnode_width+5) * x_counter;
        gridnode_loader.y = (my_gridnode_height+15) * y_counter;

        if (x_counter+1 < columns) {
            x_counter++;
        } else {
            x_counter = 0;
            y_counter++;
        }
    }
}
function gridLoaded(e:Event):void {
    var i:uint;
    var my_gridnode:Loader = Loader(e.target.loader);
    container_mc.addChild(my_gridnode);
    _xmlnewstarget = my_gridnode.name;

//||||||||||||||||||||||||||||||||||||||||   
//when a particular grid node is clicked I need to send the current _xmlnewstarget value to the LoadNewsContent function...
//||||||||||||| ||||||||||||||||||||||||

    my_tweens[Number(my_gridnode.name)]=new Tween(my_gridnode, "alpha", Strong.easeIn, 0,1,0.1, true);
    my_gridnode.contentLoaderInfo.removeEventListener(Event.COMPLETE, gridLoaded);
    my_gridnode.addEventListener(MouseEvent.CLICK, loadNewsContent);

}

function loadNewsContent(e:MouseEvent):void {
    createNewsContainer();
    getXMLNewsTarget();
    news_category = my_grid[_xmlnewstarget].@category;
    var tfnews_category:TextSplash=new TextSplash(news_category,20,16,32,false,false,0xffffff );
    tfnews_category.mouseEnabled = false;

    newstitle = my_grid[_xmlnewstarget].@newstitle;
    var tftitle:TextSplash=new TextSplash(newstitle,20,70,24,false,false,0x333333 );
    news_container_mc.addChild(tftitle);
    tftitle.mouseEnabled = false;

    news_content = my_grid[_xmlnewstarget]..news_content;
    var tfnews_content:TextSplash=new TextSplash(news_content,20,110,20,true,true,0x333333,330);
    news_container_mc.addChild(tfnews_content);
    tfnews_content.mouseEnabled = false;
    news_image = my_grid[_xmlnewstarget].@news_image;
    loadNewsImage();
    addChild(tfnews_category);
    addChild(tftitle);
    addChild(tfnews_content);

    var news_container_mc_tween = new Tween(news_container_mc, "alpha", Strong.easeIn, 0,1,0.3, true);
    news_container_mc_tween.addEventListener(Event.INIT, newsContentLoaded);
}

【问题讨论】:

    标签: actionscript-3 event-handling closures scope


    【解决方案1】:

    我不会尝试阅读您的代码(尝试处理您的格式,即使它只是缩进),但我将提供一个简化的示例:

    for (var i = 0; i < my_total; i++) {
        var closure = function() {
            // use i here
        }
    }
    

    正如您所说,当调用closure 时,它将包含i 的最后一个值(在本例中为my_total)。改为这样做:

    for (var i = 0; i < my_total; i++) {
        (function(i) {
            var closure = function() {
                // use i here
            }
        })(i);
    }
    

    这会在循环内创建 另一个 函数,该函数“捕获”i 的当前值,以便您的闭包可以引用该值。

    有关更多类似示例,另请参阅 How does the (function() {})() construct work and why do people use it?。

    【讨论】:

    • 总之:) 作用域 而不是 变量,在 Javascript 中是“封闭的”,只有新的函数声明才能创建新的作用域。
    • 感谢 Greg 的闭包函数,这真的很有帮助。我添加了代码,确保类型转换正确,并为 _xmlnewstarget 变量添加了一个设置器。我创造了完美的轮盘赌! 5 个节点 24130、01432、04312、02143、02143、14302、02143、21403、43021、24310、02143、14302、02143、43021 的值发生变化...最后一个值是 _xmlnewstarget 的值...
    • 我最终设法通过不同的途径解决了这个问题。我在 xml 中为每个新闻项目添加了一个新闻 id,并将其引用到文本容器 - text_container_mc.id = my_grid[i]。 @ID;然后我直接跳到 loadNewsContent 与 text_container_mc.addEventListener(MouseEvent.CLICK, loadNewsContent);然后在该函数中使用 e.target.id - newstitle = my_grid[e.target.id].@newstitle 链接文本字段;现在我只需要解决反向导航.. 但我认为这个问题已经解决了 ;-) 谢谢
    • @Greg 你好 Greg,关于 JavaScript,你的链接是空的:为什么是匿名函数包装器。请给我正确的链接。泰克斯。
    【解决方案2】:

    嗯,上面说了,代码有点密集,但是我想你可能有点字符串和整数的类型转换问题,“最后一个值”总是0吗?尝试进行这些更改,然后告诉我你的进展情况。

    // replace this gridnode_loader.name = i;
    gridnode_loader.name = i.toString();
    
    // explictly type this as an int
    _xmlnewstarget = parseInt(my_gridnode.name);
    
    // replace this: my_tweens[Number(my_gridnode.name)] = new Tween(......
    my_tweens[parseInt(my_gridnode.name)] = new Tween();
    

    哦,我认为一旦你得到它的工作,你应该大规模地重构这个代码块是不言而喻的。

    编辑:经过进一步研究,我认为你需要这个

    //replace this: my_gridnode.addEventListener(MouseEvent.CLICK, loadNewsContent);
    
    var anonHandler:Function = function(e:MouseEvent):void
    {
        loadNewsContent(_xmlnewstarget);
    
    };
    my_gridnode.addEventListener(MouseEvent.CLICK, anonHandler);
    

    您的loadNewsContent 已将争论从(e:MouseEvent) 更改为(id:String)

    【讨论】:

    • 对代码布局感到抱歉,我会尽快采纳您的建议;-)
    【解决方案3】:

    首先,您不需要为同一个加载器调用 addChild 两次(一次在 callGrid 中),然后在 (gridLoaded) 中调用。然后您可以尝试放入 loadNewsContent:
    news_category = my_grid[int(e.target.name)].@category;
    而不是
    news_category = my_grid[_xmlnewstarget].@category;
    因为 _xmlnewstarget 似乎范围更大,这就是每次加载操作完成时它都会更新的原因。

    【讨论】:

      猜你喜欢
      • 2021-06-08
      • 2014-09-10
      • 1970-01-01
      • 2019-05-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-05
      • 1970-01-01
      相关资源
      最近更新 更多