【问题标题】:Jquery trigger event appends content but DOM not ready afterJquery触发事件追加内容但DOM未准备好之后
【发布时间】:2012-02-16 19:22:13
【问题描述】:

我正在努力解决我认为很简单的事情。我知道我以前在没有 JQuery 的普通旧 javascript 中也遇到过同样的问题。我尝试做的是:

//When the postal code blurs, lookup the city, country, province
$('#codePostal').blur(function(){
    $.get('/fr/radio-telethon/ajax_code_postal.php', {code_postal: $('#codePostal').val()}, function(data){
        if(data.code_postal.toLowerCase() == $('#codePostal').val().toLowerCase()){
            $('#ville').val(data.ville);
            $('#pays').val(data.pays);
            $('#pays').trigger('change');
            $('#province').val(data.province);
            $('#province').trigger('change');
        }
    });
});

这基本上调用了一个邮政编码查找脚本并返回一个包含数据的对象。数据本身是正确的,我可以提醒它,它显示正常。问题是#pays(英语中的国家)上的更改触发器重新加载了#province(州)内的信息,并且似乎 DOM 正在苦苦挣扎并且没有加载信息。

如果我在国家的触发器和省份的 val 之间发出警报,我可以正确设置省份。我用来将省份添加到省份框的方法如下:

//Empty the provinces
$('#province').empty();

//Get the new data
$.get('/include/radio-telethon/formulaire-ajax.php', {pays: code}, function(data){

    //Loop the items
    for(i in data.options){
        $('#province').append('<option value="'+data.options[i].value+'">'+data.options[i].label+'</option>');
    }

    //Setup the label
    $('#labelProvince').html(data.label);

});

所以我的猜测是 APPEND 搞砸了一切并使整个 DOM 徘徊,这就是为什么我似乎不能做 $('#province').val(data.province);

是我吗?或者有没有我似乎找不到的魔术......

【问题讨论】:

  • 哦,我也试过 $('#province').ready(function(){ $(this).val(data.province); });

标签: jquery


【解决方案1】:

change 元素的 change 事件处理程序包括一个异步的 AJAX 调用。所以它可能不会在下面的代码运行之前返回。一个好的解决方法是运行此代码:

        $('#province').val(data.province);
        $('#province').trigger('change');

在您的$.get() 呼叫的回调中:

//setup a variable to store the province once it's returned from the server
var province = '';
$('#codePostal').blur(function(){
    $.get('/fr/radio-telethon/ajax_code_postal.php', {code_postal: $('#codePostal').val()}, function(data){
        if(data.code_postal.toLowerCase() == $('#codePostal').val().toLowerCase()){
            $('#ville').val(data.ville);
            $('#pays').val(data.pays);
            $('#pays').trigger('change');

            //save the province so it can be used later
            province = data.province;
        }
    });
});

//Get the new data
$.get('/include/radio-telethon/formulaire-ajax.php', {pays: code}, function(data){

    //Loop the items
    for(i in data.options){
        $('#province').append('<option value="'+data.options[i].value+'">'+data.options[i].label+'</option>');
    }

    //Setup the label
    $('#labelProvince').html(data.label);

    //update the #province element using the saved province variable
    $('#province').val(province).trigger('change');
});

您的代码也可以利用一些优化:

var province = '';
$('#codePostal').blur(function(){
    var thisValue = this.value;//cache `this.value` since it's used multiple times
    $.get('/fr/radio-telethon/ajax_code_postal.php', {code_postal: thisValue}, function(data){
        if(data.code_postal.toLowerCase() == thisValue.toLowerCase()){
            $('#ville').val(data.ville);
            $('#pays').val(data.pays).trigger('change');//notice the function chaining
            province = data.province;
        }
    });
});
$('#pays').change(function () {

    //Get the new data
    $.get('/include/radio-telethon/formulaire-ajax.php', {pays: code}, function(data){
        var output = [];

        //Loop the items, using a much faster loop, also buffering the output so it gets added to the DOM at once which creates A LOT less overhead

        for(var i = 0, len = data.options.length; i < len; i++){
            output.push('<option value="'+data.options[i].value+'">'+data.options[i].label+'</option>');
        }

        //this will empty the #province element and append the output at once
        $('#province').html(output.join('')).val(province).trigger('change');

        //Setup the label
        $('#labelProvince').html(data.label);

    });
});

这是一个 JSPerf,用于显示我在上面使用的循环中的性能提升:http://jsperf.com/jquery-each-vs-for-loops/2

【讨论】:

  • @gdoron 感谢您的编辑,但它删除了我写的一段,所以我回滚了。
  • 哦!对不起!!!但是您仍然可以正确缩进代码... =)没有阅读答案,但得到我的 +1...
  • 感谢 foreach 上的性能测试,我会考虑到未来。现在我一般只有 13 个元素,所以它并没有真正放慢速度,但是对于更大的数组,我一定会记住这一点
【解决方案2】:

在 Jasper 的帮助下,我找到了一个更适用于我的问题的解决方案,所以我会为 Jasper 的解决方案点赞,但我会将我的解决方案标记为答案。

我使用的是我将data.province传递给触发器的extraParameters并添加了一个

//When country changes, show/hide the province/region
$('#pays').change(function(event, province){

    ........ other code .......

    //If there is a province in the parameter, set it
    if(province !== 'undefined'){
        $('#province').val(province);
        $('#province').trigger('change');
    }


    ........ other code .......

});

在#pays.change 处理程序中使用:

$('#pays').trigger('change', data.province);

这样,我不会像 Jasper 那样创建全局变量,而且我仍然可以检测到更改事件的触发器是否在省内传递。

谢谢贾斯珀

【讨论】:

    猜你喜欢
    • 2015-03-08
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多