jQuery自定义函数在每次迭代中丢失范围?

时间:2011-08-06 15:39:34

标签: jquery

我正在尝试使用jQuery函数编写自己的模态弹出窗口。但是,我遇到了一个问题,即我创建的最新窗口将是所有控件显示的窗口。我显然做了一些完全错误的事情。

请参阅以下jsFiddle:http://jsfiddle.net/Ff34s/5/

我希望以下代码的结果......

$(document).ready(function () {

    // Put the editor in a dialog window
    $("#test1").gttdialog({
    });

    // Put the editor in a dialog window
    $("#test2").gttdialog({
    });

    $("#test1").gttdialog.show();
});

...显示包含 1 的div,但我得到包含 2 的div。

这是为什么?我只能猜测出现错误的代码块是在每次迭代期间:

    // Create the dialog window
    this.each(function () {
        var $this = $(this);
        var controls = renderDialog($this);
        hide(controls);

        // Handle the resize event
        $(window).resize(function () {
            keepCentered(controls.dialog);
            maintainMask(controls.mask);
        });

        $this.gttdialog.show = function () {
            show(controls);
        };
        $this.gttdialog.hide = function () {
            hide(controls);
        };
    });

只有最新创建的变量controls似乎仍在范围内。

更新

问题是由于:

$this.gttdialog.show = function () {
    show(controls);
};
$this.gttdialog.hide = function () {
    hide(controls);
};

他们在第二次迭代时被重新分配。如何使这项工作适用于所有迭代?我显然对jQuery函数做了一些完全错误。

2 个答案:

答案 0 :(得分:3)

问题是

 $this.gttdialog.show = function () {
     show(controls);
 };

gttdialog是由所有 jQuery对象共享的属性(它指的是$.fn.gttdialog)。每当你拨打$("#test2").gttdialog时,你都会覆盖这个属性。

因此,您需要做的是将控件附加到此特定实例。你可以这样做:

$this.gttdialogControls = { // you should probably choose a better name ;)
     show: function () {
         show(controls);
     },
     hide: function () {
         hide(controls);
     }
};

但是你必须保持对该对象的引用,因为调用jQuery将创建一个新的jQuery对象:

var d = $("#test1").gttdialog({});
d.gttdialogContols.show();
// won't work:
$("#test1").gttdialogContols.show();

另一种选择是使用.data()

更新:考虑下面的代码,我认为您可以轻松实现。我会使用.data()存储控件:

this.each(function () {
    var $this = $(this);
    var controls = renderDialog($this);
    hide(controls);
    //...
    $this.data('gttcontrols', controls);
});

// Add the show and hide functions
$.fn.gttShowDialog = function () {
    return this.each(function() {
        show($(this).data('gttcontrols'));
    });       
};
$.fn.gttHideDialog = function () {
    return this.each(function() {
        hide($(this).data('gttcontrols'));
    });
};

然后你不必处理身份证。

答案 1 :(得分:0)

我通过向函数创建的控件添加唯一ID来修复它:

$dialog.attr("id", id + "_Dialog");
$header.attr("id", id + "_Header");
$container.attr("id", id + "_Container");
$mask.attr("id", id + "_Mask");

然后我将以前在每个迭代器中的函数修改为全局jQuery函数:

// Add the show and hide functions
$.fn.gttShowDialog = function () {
    var controls = $.fn.gttdialog._getDialogControls(this[0].id);
    show(controls);
};
$.fn.gttHideDialog = function () {
    var controls = $.fn.gttdialog._getDialogControls(this[0].id);
    hide(controls);
};

然后我需要做的就是通过它们唯一的ID检索控件并将它们传递给适当的方法:

$.fn.gttdialog._getDialogControls = function (id) {
    var controls = [];
    controls["dialog"] = $("#" + id + "_Dialog");
    controls["header"] = $("#" + id + "_Header");
    controls["container"] = $("#" + id + "_Container");
    controls["mask"] = $("#" + id + "_Mask");
    return controls;
};

现在要设置并调用,我只需执行以下操作:

$("#waitElement").gttdialog();
$("#waitElement").gttShowDialog();

工作小提琴here