JQuery.append()之后,怎么保证append()成功了,且dom也更新完毕了再去操作append进去的元素

需求如下:

  1. 循环向页面插入列表

  2. 列表中有图片,根据接口获取图片真实宽高并赋值给图片元素

  3. 元素成功插入且dom更新了再去赋值(我这边给图片元素赋值已成功,按代码顺序就行)

  4. 根据图片高度定位图片下面的一个元素到图片中心(此处document.getElementById(id)为null,上面都可以了下面却不可以,真**)

  5. 图片左右无元素,上下有元素,因此使用一般的css居中不可行
    (非要搞的话height: calc(100% - 11vw);类似的方法也行)

类似下面这个问题

http://stackoverflow.com/questions/6068955/jquery-function-after-append

我就想知道有没有什么比较好的方法能确保append之后能成功拿到对应的元素id

阅读 14.5k
7 个回答

jq 对象有一个context属性,代表这个节点所在的上下文环境

在节点 未附加给哪个节点的情况下,它的context是undefined的

var $li=$('<li>'); //创建一个节点,但没有附加给哪个节点
var $test=$($li,$('body'));//在当前body上下文环境中查找这个节点
            
console.log($li) // => [li]
console.log($li.length); // => 1
console.log($test); // => [li, selector: "", context: undefined]
console.log($test.length); // => 1

在你的第1条中循环向页面插入列表,那么也就是说会创建这个列表节点(创建为jq节点赋值给变量),再将其附加到目标节点,那么我们就可以通过 $(目标).find(列表项).length>0就可以判断他是否已附加成功

如下示例代码

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

            for (var i = 0; i < 3; i++) {

                var $li = $('<li>'+i+'</li>').appendTo($list);
                
                if($list.find($li).length>0){
                    // 处理图片
                    console.log($li.text());
                    // => 1
                    // => 2
                    // => 3
                }
            }

擴展一下 jquery 的 append

jQuery.fn.extend({
  appendMore: function(content, callback) {
    // 隨機的 class name
    var rand_class_name = "appendMore_" + Math.random().toString(36).substr(2, 5);
    var lis_item = this.each(function() {
      // 有 append 的項目,都有此隨機名稱
      $(this).append(content).addClass(rand_class_name);
    });
    // 在 append 結束後呼叫,並傳入隨機名稱,也就是這次有變更到的項目
    if (typeof(callback) == "function"){
        // 沒意外的話,理應撈的到東西
        callback(rand_class_name);
    }
    $("." + rand_class_name).removeClass(rand_class_name);
    return lis_item;
  }
});

使用範例

// 例子 
$("a").appendMore("cccc", function(append_class_name){
    // 這次有變更的項目,他們的 id
    $("." + append_class_name + "").each(function(){
        console.log($(this).attr("id"));
    });
});

// 例子
var create_count = 0;
function createItem(){
    create_count++;
    return '<span id="item-' + create_count + '">' + create_count + '</span>';
}
$("span").appendMore(createItem, function(append_class_name){
    // 這次創建的項目,他們的 id
    $("." + append_class_name + " span").each(function(){
        console.log($(this).attr("id"));
    });
});

https://jsfiddle.net/cwen0708/xa7o3h2p/

我也遇到了类似的问题,翻看了一下stackoverflow里的答案,觉得这个理由是说的通的:在append之后,DOM树更新了,但是浏览器的redraw还没有完成,这个时候对刚append上去的元素做操作是会失败的。比较简单的解决方案一个是加setTimeout,时间为0都可以(在我遇到的问题中是这样);或者,在append函数之后加.hide().show(),但是还不清楚如果是移动端,低端机上这样做元素会不会有闪动。

操作元素之前,先看看操作的元素是否存在。

if($('#foo').length){
    //appended
}else{
    //not appended
}
var str="";
for(var i=0;i<leng.length;i++){
    str="<img id='"+i+"' /><h3 id='h"+i+"'></h3>"
    $(".list").append(str);
    // ------------------
    // 如果 $(".list") 存在, 则 $('#h' + i).length 必然存在
    // ------------------
    // 在下一行设置断点, 查看 DOM 结构, 打印 $('#h' + i).length
    setImageHeight(imgurl, i,100);//图片url,图片id,100是图片宽度,单位是VW    
}

setImageHeight 中异步调用的 ajax({async: true}), 那在异步执行 success 之前, 还做了什么事情?
建议你在 $(".list").append(str) 之后设置断点, 调试一下.

var li='<li id="1"></li><li id="2"></li>';
$("ul").append(li).on("click","li",function(){
alert($(this).attr("id"))
})

如果要确保在函数执行的时候append操作已经完成的话,最简单的办法应该是setTimeout(fun, 0)了; 浏览器会在完成延宕事件以及DOM操作之后再通知setTimeout执行调用的函数。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题