简体   繁体   English

初始化jQuery对象(元素),然后将其放置在DOM中

[英]Initialize jQuery Object (Element) Before Placing it in the DOM

So, for a project I'm working on, I need to make users in a user selector sortable by network. 因此,对于我正在从事的项目,我需要使用户选择器中的用户可以按网络排序。 The current way I am doing this is by creating the user: 我目前的操作方式是创建用户:

clone += '<li class="'+ this.gender +'" data-id="'+ this._id +'">';
clone += '<img src="'+ this.image +'" />';
clone += '<span>'+ this.name +'</span>';
clone += '</li>';

Then having a jQuery object with the key being the network name and the value being an array of user ids, like: 然后有一个jQuery对象,其键为网络名称,值为用户ID数组,例如:

{
  Network 1: [1,2,3,4]
  Network 2: [5,6,7,8]
}

Then, when a network is selected, I sort through all of li elements and match them against the array of ids and if it doesn't contain the id, hide the li element, like so: 然后,当选择一个网络时,我对所有li元素进行排序,并将它们与id数组匹配,如果它不包含id,则隐藏li元素,如下所示:

for(var i = 0, n = education_ids[network].length;i < n;i++){
   $('.friends-list li[data-id='+ education_ids[network][i]+']').removeClass('chosen_network');
}

Unfortunately, it's really inefficient because basically for every iteration of the loop, the jQuery selector iterates over all the li elements, so if there are 1000 friends and 100 ids in the network, that's 100 1000 step iterations. 不幸的是,它的效率很低,因为基本上对于循环的每次迭代,jQuery选择器都会遍历所有li元素,因此,如果网络中有1000个朋友和100个id,则是100次1000步迭代。

As a solution to this problem, I thought I might be able to add the jQuery objects to the array rather than the ids, so that way I could just iterate over them and add the classes (reducing the iterations 1000x). 作为此问题的解决方案,我认为我可以将jQuery对象而不是id添加到数组中,这样我就可以对其进行迭代并添加类(将迭代次数减少1000x)。 Here is how I'm currently trying to do that: 这是我目前正在尝试执行的操作:

clone += '<li class="'+ this.gender +'" data-id="'+ this._id +'">';
clone += '<img src="'+ this.image +'" />';
clone += '<span>'+ this.name +'</span>';
clone += '</li>';

if(this.education){
    for(var i = 0, n = this.education.length; i < n ; i++){
    if(education[this.education[i].school.name]){
       education[this.education[i].school.name]++;
       education_ids[this.education[i].school.name].push($(clone));
    } else {
        education[this.education[i].school.name] = 1;
        education_ids[this.education[i].school.name] = [$(clone)];
    }
}
}

The relevant part is when I: 相关部分是当我:

.push($(clone)

or initialize the array by doing: 或通过执行以下操作初始化数组:

[$(clone)]

Unfortunately, this technique doesn't work because at this point in my program, the elements actually haven't been added to the DOM. 不幸的是,该技术不起作用,因为在我的程序中,实际上还没有将元素添加到DOM中。 So, my question is as follows: 因此,我的问题如下:

Is it possible to initialize these jQuery references BEFORE they are put into the DOM and if so, how would I do that? 是否可以在将这些jQuery引用放入DOM之前对其进行初始化,如果是的话,我该怎么做?

And, if I can't do that, can you think of a more efficient way for me to solve this problem. 而且,如果我无法做到这一点,您能为我解决一个更有效的方法吗?

Just for reference, I am trying to make this faster because with the current strategy the looping freezes the DOM for anywhere between 1 and 2 seconds—not exactly the ideal experience for a user. 仅供参考,我试图使其速度更快,因为使用当前策略,循环会将DOM冻结1到2秒之间的任何时间-并非用户的理想体验。

Thank you so much for any help you can give! 非常感谢您提供的任何帮助!

EDIT: Progress made, but hitting an error! 编辑:取得了进展,但遇到错误!

Ok, so I've made a little progress. 好的,我取得了一些进展。 Using the jQuery selector actually works, so now I'm doing: 使用jQuery选择器实际上有效,所以现在我正在做:

    clone += '<li class="'+ this.gender +'" data-id="'+ this._id +'">';
    clone += '<img src="'+ this.image +'" />';
    clone += '<span>'+ this.name +'</span>';
    clone += '</li>';

    clone = $(clone)

    if(this.education){
        for(var i = 0, n = this.education.length; i < n ; i++){
            if(education[this.education[i].school.name]){
                education[this.education[i].school.name]++;
                education_ids[this.education[i].school.name].push(clone);
            } else {
                education[this.education[i].school.name] = 1;
                education_ids[this.education[i].school.name] = [clone];
            }
        }
    }

placeholder.push(clone);

And then after looping through all of the friends, 然后遍历所有朋友之后,

$('.friends-list').append(placeholder).fadeIn();

I think that should be working, but now I'm getting: 我认为应该可以,但是现在我得到了:

Uncaught Error: NOT_FOUND_ERR: DOM Exception 8

Thoughts? 思考?

EDIT: More progress, fixed the error, but sorting not working 编辑:更多进度,修复了错误,但排序不起作用

Ok, so I fixed the error by switching placeholder to an empty div like @Artimuz did, but now the sorting isn't working. 好的,所以我通过像@Artimuz一样将占位符切换到一个空的div来解决错误,但是现在排序不起作用了。 So, basically I sort like this: 所以,基本上我是这样的:

if("network is clicked and it was already selected") {
    for(var person in education_ids[network]){
        person.removeClass('chosen_network');
    }
} else //if it wasn't already selected {
     for(var person in education_ids[network]){
        person.addClass('chosen_network').removeClass('disabled');
}
}

Unfortunately, this doesn't work. 不幸的是,这不起作用。 I'm getting: 我越来越:

Uncaught TypeError: Object 0 has no method 'addClass'

And so, once again I ask: thoughts? 因此,我再次问:想法?

The slowest part of any javascript is touching the DOM. 任何JavaScript中最慢的部分是接触DOM。 Store your users: 存储您的用户:

var users = [
    {
        name : "dave",
        gender : "male",
        image : "omg.jpg"
    }
];

Store your networks (assuming you have less networks than users): 存储您的网络(假设您的网络少于用户):

var networks = [
    [2,5,8]
];

Draw appropriately when required: 根据需要适当绘制:

var html = "";
for(var i = networks[current].length; i--;){
    var id = networks[current][i];
    html += '<li class="'+ users[id].gender +'" data-id="'+ id +'">';
    html += '    <img src="'+ users[id].image +'" />';
    html += '    <span>'+ users[id].name +'</span>';
    html += '</li>';
}
$(container).html(html);

This way you iterate once over each user, the pure data which is the user. 这样,您可以遍历每个用户一次,即用户的纯数据。 And you touch the DOM once to draw everything which is required. 然后,您只需触摸DOM即可绘制所需的所有内容。

This has the drawback of redrawing all the currently displayed users, but if that is an issue (if most people are in all of the networks for example) the solution can be modified to cache which users have already been drawn, and add the new users more discretely. 这具有重新绘制所有当前显示的用户的缺点,但是如果这是一个问题(例如,如果大多数人在所有网络中),则可以修改解决方案以缓存已绘制的用户,并添加新用户更离散地。

OK so I'll try to summarize some of your bugs here : 好的,所以我将在这里尝试总结您的一些错误:

For the first bug 对于第一个错误

No idea what was your problem. 不知道你怎么了 For me that worked. 对我来说,那很奏效。

jsfiddle.net/3xqx5 jsfiddle.net/3xqx5

For the NOT_FOUND_ERR exception 对于NOT_FOUND_ERR异常

It's just that you were trying to add a array , a pure javascript object, to the DOM. 只是您要向DOM添加一个array (纯JavaScript对象)。 JQuery.append requires a jQuery object or a DOM element ! JQuery.append需要jQuery对象或DOM元素! So you can put you items in a placeholder <div> or you iterate over your array and add items one by one. 因此,您可以将项目放在占位符<div>或者遍历数组并一个接一个地添加项目。

jsfiddle.net/3xqx5/1 jsfiddle.net/3xqx5/1

For the last error Object 0 has no method 'addClass' 对于最后一个错误, Object 0 has no method 'addClass'

The for statement you have done is not consistent, at least because it do a copy of each item at each iteration. 您执行的for语句不一致,至少是因为它在每次迭代时都会复制每个项目。 Work directly on array elements by doing a for(var i=0; i < a.length; i++) 通过执行for(var i=0; i < a.length; i++)直接在数组元素上工作

jsfiddle.net/3xqx5/2 jsfiddle.net/3xqx5/2

Building HTML using string concatenation is horrible, please avoid that. 使用字符串连接构建HTML太可怕了,请避免这种情况。

As per @Sinetheta's data structure 根据@Sinetheta的数据结构

var template = [
    "<li>",
        "<img></img>",
        "<span></span>",
    "</li>"
].join("");

var nodes = [];
for(var i = networks[current].length; i--;){
    var id = networks[current][i],
        user = users[id];

    var li = $(template);
    li.addClass(user.gender);
    li.data("id", id);

    var children = node.children();
    children.eq(0).prop("src", user.image);
    children.eq(1).text(user.name);

    nodes.push(li);
}

$.each(nodes, function (_, node) {
    $(container).append(node);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM