jQuery的执行顺序使用$.load()异步问题(bootstrap modal)

jQuery order of execution using $.load() asynchronous problems (bootstrap modal)

本文关键字:异步 问题 modal bootstrap load 执行 顺序 jQuery      更新时间:2023-09-26

我有一个奇怪的问题与jQuery的操作顺序。下面的代码在ie9 &的问世。在ie11、firefox和chrome中,它根本不起作用。它将执行并打开新窗口,但load()不会触发。我可以在事件链中放置一个警报,并且load()可以在firefox和ie11中工作…在chrome中,它仍然永远不会运行load()。

起初,我认为load的目标只是还没有被添加到DOM中,警报创建的暂停给了它创建的时间。我在完全相同的位置添加了一个睡眠计时器来测试这个理论——它不起作用,不管计时器设置多长时间。

关于这个问题的任何想法都会很有帮助。谢谢大家!
    function openWindow(id, which, windowOptions) {
        $('<div>')
        .attr('id', 'GenericWindow')
        .addClass('modal hide fade')
        .html('<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="WindowHeader">Loading...</h3>'
        + '</div><div id="divWindowContent" class="modal-body">Content!</div><div id="WindowButtons" class="modal-footer"><input type="button" id="btnWindowCancel" value="Cancel" class="btn" data-dismiss="modal" aria-hidden="true" />'
        + '<input type="button" id="btnWindowSave" value="Save" class="btn btn-info" />')
        .modal({"keyboard":"true"})
        .on('hidden', function (e) {
            var src = $(e.target);
            if (!src.hasClass('popover-link')) {
                $('#GenericWindow').remove();
                clearErrors();
            }
        });
        if (!windowOptions) {
            //THIS IS THE ALERT.
            alert('huh');
            var link = '@Url.Action("replace", "Operations")'
            link = link.replace("replace", which);
            $('#divWindowContent').load(link, { id: id }, function (response, status, xhr) {
                if (status == "error") {
                    var msg = "Error loading details : ";
                    $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                }
            });
        }
        else {
            if (windowOptions.action) {
                var action = windowOptions.action;
                    var link = '@Url.Action("view", "controller", new { Area = "MvcMembership" })';
                if (!$.isNull(action.area))
                    link = link.replace("MvcMembership", action.area);
                else
                    link = link.replace("/MvcMembership", "");
                link = link.replace("view", action.view);
                link = link.replace("controller", action.controller);
                $('#divWindowContent').load(link, action.values, function (response, status, xhr) {
                    if (status == "error") {
                        var msg = "Error loading details : ";
                        $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                    }
                });
            }
            else {
                $('#divWindowContent').html(windowOptions.text);                    
            }
            $('#WindowHeader').html(windowOptions.title);
            if (windowOptions.hideButtons) {
                $('#WindowButtons').remove();
                $('#GenericWindow .close').remove();
            }
            $('#GenericWindow').css('width', windowOptions.width);
            $('#GenericWindow').css('height', windowOptions.height);
        }
    }

编辑:我应该注意的是,如果你在打开一个新的模态之前使用一个函数来关闭页面上任何打开的模态,appendTo('body')不起作用。您必须使用"创建变量"解决方案。同样值得注意的是,创建一个变量要快得多,特别是在第一个模态打开之后。

您动态创建的窗口不会被选择器正确捕获,直到您将其作为页面中的元素添加(无论如何对于Chrome)。

要解决这个问题,您可以将GenericWindow附加到body,并在关闭窗口时将其解散。

或者将元素存储在一个变量中,并在该变量上调用load。

Chrome的工作示例:

方案一:http://jsfiddle.net/4c3hu/

$(document).ready(function(){
    openWindow('blerg', 'test', null);
});

function openWindow(id, which, windowOptions) {
        $('<div>')
        .attr('id', 'GenericWindow')
        .addClass('modal hide fade')
        .html('<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="WindowHeader">Loading...</h3>'
    + '</div><div id="divWindowContent" class="modal-body">Content!</div><div id="WindowButtons" class="modal-footer"><input type="button" id="btnWindowCancel" value="Cancel" class="btn" data-dismiss="modal" aria-hidden="true" />'
    + '<input type="button" id="btnWindowSave" value="Save" class="btn btn-info" />')
        .modal({"keyboard":"true"})
        .appendTo('body')
        .on('hidden', function (e) {
            var src = $(e.target);
            if (!src.hasClass('popover-link')) {
                $('#GenericWindow').remove();
                clearErrors();
            }
        });
        if (!windowOptions) {
            //THIS IS THE ALERT.
            console.log('huh');
            var link = '@Url.Action("replace", "Operations")'
            link = link.replace("replace", which)
            link = '/echo/html/'
            console.log(link);
            $('#divWindowContent').load(link, { id: id }, function (response, status, xhr) {
                console.log('after load');
                if (status == "error") {
                    var msg = "Error loading details : ";
                    $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                }
            });
        }
        else {
            if (windowOptions.action) {
                var action = windowOptions.action;
                var link = '@Url.Action("view", "controller", new { Area = "MvcMembership" })';
                if (!$.isNull(action.area))
                    link = link.replace("MvcMembership", action.area);
                else
                    link = link.replace("/MvcMembership", "");
                link = link.replace("view", action.view);
                link = link.replace("controller", action.controller);
                $('#divWindowContent').load(link, action.values, function (response, status, xhr) {
                    if (status == "error") {
                        var msg = "Error loading details : ";
                        $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                     }
                });
            }
            else {
                $('#divWindowContent').html(windowOptions.text);                    
            }
            $('#WindowHeader').html(windowOptions.title);
            if (windowOptions.hideButtons) {
                $('#WindowButtons').remove();
                $('#GenericWindow .close').remove();
            }
            $('#GenericWindow').css('width', windowOptions.width);
            $('#GenericWindow').css('height', windowOptions.height);
        }
    }

方案二:http://jsfiddle.net/4c3hu/1/

$(document).ready(function(){
    openWindow('blerg', 'test', null);
});

function openWindow(id, which, windowOptions) {
        var $elem = $('<div>')
        .attr('id', 'GenericWindow')
        .addClass('modal hide fade')
        .html('<div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button><h3 id="WindowHeader">Loading...</h3>'
        + '</div><div id="divWindowContent" class="modal-body">Content!</div><div id="WindowButtons" class="modal-footer"><input type="button" id="btnWindowCancel" value="Cancel" class="btn" data-dismiss="modal" aria-hidden="true" />'
        + '<input type="button" id="btnWindowSave" value="Save" class="btn btn-info" />')
        .modal({"keyboard":"true"})
        .on('hidden', function (e) {
            var src = $(e.target);
            if (!src.hasClass('popover-link')) {
                $('#GenericWindow').remove();
                clearErrors();
            }
        });
        if (!windowOptions) {
            //THIS IS THE ALERT.
            console.log('huh');
            var link = '@Url.Action("replace", "Operations")'
            link = link.replace("replace", which)
            link = '/echo/html/'
            console.log(link);
            $elem.load(link, { id: id }, function (response, status, xhr) {
                console.log('after load');
                if (status == "error") {
                    var msg = "Error loading details : ";
                    $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                }
            });
        }
        else {
            if (windowOptions.action) {
                var action = windowOptions.action;
                var link = '@Url.Action("view", "controller", new { Area = "MvcMembership" })';
                if (!$.isNull(action.area))
                    link = link.replace("MvcMembership", action.area);
                else
                    link = link.replace("/MvcMembership", "");
                link = link.replace("view", action.view);
                link = link.replace("controller", action.controller);
                $elem.load(link, action.values, function (response, status, xhr) {
                    if (status == "error") {
                        var msg = "Error loading details : ";
                        $('#divWindowContent').html(msg + xhr.status + " " + xhr.statusText);
                    }
                });
            }
            else {
                $('#divWindowContent').html(windowOptions.text);                    
            }
            $('#WindowHeader').html(windowOptions.title);
            if (windowOptions.hideButtons) {
                $('#WindowButtons').remove();
                $('#GenericWindow .close').remove();
            }
            $('#GenericWindow').css('width', windowOptions.width);
            $('#GenericWindow').css('height', windowOptions.height);
        } 
    }

您的问题不是.load()函数,而是.modal()将新元素附加到DOM的方式。在不同浏览器中不一致。

另外,jQuery的选择器只会查看已经添加到DOM中的内容。

这里有一个小提琴来说明这个问题:

http://jsfiddle.net/4NdNQ/

这将在一些浏览器中打印0, 1,在其他浏览器中打印1, 1

您要做的是保持对父元素的引用并搜索它的子元素,而不是搜索所有DOM元素。下面的代码说明了这一点,它总是能在任何浏览器中找到包含的<div>:

http://jsfiddle.net/4NdNQ/1/

这就是奇迹发生的原因:

var container = $('<div>').html('<div id=myElementId></div>');
// container now only exists in the script stack, it's not present in the DOM
$("#myElementId"); // <- this selects nothing
container.find("#myElementId").load( /* parameters */); // <- this now works

ED: @YanBrunet的回答也解释了这个问题,但我将把这个作为解决它的另一种方法-因为它是一个较小的更改