需要帮助来加速这个 jQuery 过程

发布于 2024-09-26 17:06:56 字数 9211 浏览 3 评论 0原文

我创建了以下流程。基本上,它循环遍历一个具有多层嵌套列表的巨大无序列表,并创建一个 2 层嵌套无序列表。它运行良好,但在 IE7 中非常慢。 FireFox 和 Safari 没有什么大问题。不太擅长 jQuery 我想知道是否可以通过使用更好/更快/更智能的函数来加快速度。由于我使用的 CMS,我无法更改输出,也无法更改我使用的 jQuery 版本(1.2.6)。

这就是我所拥有的;

$('ul#mainnav li ul li').each(function() {
    // add level class
    $(this).addClass('depth-'+$(this).parents('ul').length);
    // make uls siblings in stead of children
    $($(this).children('ul')).insertAfter($(this));
});
// take all lis out of their uls
$('ul#mainnav li ul').each(function() {
    $(this).replaceWith($(this).children());                
});
// wrap chidlren lis with div
$('ul#mainnav li').each(function() {
    $(this).children('li:first').before('<ul class="megamenu" />');     
    $(this).children('.megamenu').append($(this).children('li'));
});
// apply plugin easyLisSplitter
$('.megamenu').easyListSplitter({ 
    colNumber: 5
});

有什么想法吗?如果需要更多信息,请告诉我!

干杯

编辑:

感谢所有回复。还没有尝试一切。使用 var $this = $(this);速度加快了 20 毫秒。好吧,我会接受这些。仍然欢迎所有帮助!这是之前的标记:

<ul id="mainnav">
<li><a href="#">A-1</a>
    <ul>
        <li><a href="#">A-1-1</a>
            <ul>
                <li><a href="#">A-1-1-1</a></li>
                <li><a href="#">A-1-1-2</a></li>
                <li><a href="#">A-1-1-3</a></li>
            </ul>
        </li>
        <li><a href="#">A-1-2</a></li>
        <li><a href="#">A-1-3</a>
            <ul>
                <li><a href="#">A-1-3-1</a></li>
                <li><a href="#">A-1-3-2</a></li>
                <li><a href="#">A-1-3-3</a></li>
            </ul>
        </li>
        <li><a href="#">A-1-4</a>
            <ul>
                <li><a href="#">A-1-4-1</a></li>
                <li><a href="#">A-1-4-2</a></li>
                <li><a href="#">A-1-4-3</a></li>
                <li><a href="#">A-1-4-4</a></li>
                <li><a href="#">A-1-4-5</a></li>
            </ul>
        </li>
        <li><a href="#">A-1-5</a>
            <ul>
                <li><a href="#">A-1-5-1</a></li>
                <li><a href="#">A-1-5-2</a></li>
                <li><a href="#">A-1-5-3</a></li>
                <li><a href="#">A-1-5-4</a></li>
                <li><a href="#">A-1-5-5</a></li>
            </ul>
        </li>
    </ul>
</li>
<li><a href="#">B-1</a>
    <ul>
        <li><a href="#">B-1-1</a>
            <ul>
                <li><a href="#">B-1-1-1</a></li>
                <li><a href="#">B-1-1-2</a></li>
                <li><a href="#">B-1-1-3</a></li>
            </ul>
        </li>
        <li><a href="#">B-1-2</a></li>
        <li><a href="#">B-1-3</a>
            <ul>
                <li><a href="#">B-1-3-1</a></li>
                <li><a href="#">B-1-3-2</a></li>
                <li><a href="#">B-1-3-3</a></li>
            </ul>
        </li>
        <li><a href="#">B-1-4</a>
            <ul>
                <li><a href="#">B-1-4-1</a></li>
                <li><a href="#">B-1-4-2</a></li>
                <li><a href="#">B-1-4-3</a></li>
                <li><a href="#">B-1-4-4</a></li>
                <li><a href="#">B-1-4-5</a></li>
            </ul>
        </li>
        <li><a href="#">B-1-5</a>
            <ul>
                <li><a href="#">B-1-5-1</a></li>
                <li><a href="#">B-1-5-2</a></li>
                <li><a href="#">B-1-5-3</a></li>
                <li><a href="#">B-1-5-4</a></li>
                <li><a href="#">B-1-5-5</a></li>
            </ul>
        </li>
    </ul>
</li>

这是之后的内容;

<ul id="mainnav">
<li><a href="#">A-1</a>
    <div class="listContainer1">
        <ul class="megamenu listCol1">
            <li class="depth-2"><a href="#">A-1-1</a></li>
            <li class="depth-3"><a href="#">A-1-1-1</a></li>
            <li class="depth-3"><a href="#">A-1-1-2</a></li>
            <li class="depth-3"><a href="#">A-1-1-3</a></li>
            <li class="depth-2"><a href="#">A-1-2</a></li>
        </ul>
        <ul class="listCol2 megamenu">
            <li class="depth-2"><a href="#">A-1-3</a></li>
            <li class="depth-3"><a href="#">A-1-3-1</a></li>
            <li class="depth-3"><a href="#">A-1-3-2</a></li>
            <li class="depth-3"><a href="#">A-1-3-3</a></li>
            <li class="depth-2"><a href="#">A-1-4</a></li>
        </ul>
        <ul class="listCol3 megamenu">
            <li class="depth-3"><a href="#">A-1-4-1</a></li>
            <li class="depth-3"><a href="#">A-1-4-2</a></li>
            <li class="depth-3"><a href="#">A-1-4-3</a></li>
            <li class="depth-3"><a href="#">A-1-4-4</a></li>
            <li class="depth-3"><a href="#">A-1-4-5</a></li>
        </ul>
        <ul class="listCol4 megamenu">
            <li class="depth-2"><a href="#">A-1-5</a></li>
            <li class="depth-3"><a href="#">A-1-5-1</a></li>
            <li class="depth-3"><a href="#">A-1-5-2</a></li>
            <li class="depth-3"><a href="#">A-1-5-3</a></li>
            <li class="depth-3"><a href="#">A-1-5-4</a></li>
        </ul>
        <ul class="listCol5 megamenu last">
            <li class="depth-3"><a href="#">A-1-5-5</a></li>
        </ul>
    </div>
</li>
<li><a href="#">B-1</a>
    <div class="listContainer2">
        <ul class="megamenu listCol1">
            <li class="depth-2"><a href="#">B-1-1</a></li>
            <li class="depth-3"><a href="#">B-1-1-1</a></li>
            <li class="depth-3"><a href="#">B-1-1-2</a></li>
            <li class="depth-3"><a href="#">B-1-1-3</a></li>
            <li class="depth-2"><a href="#">B-1-2</a></li>
        </ul>
        <ul class="listCol2 megamenu">
            <li class="depth-2"><a href="#">B-1-3</a></li>
            <li class="depth-3"><a href="#">B-1-3-1</a></li>
            <li class="depth-3"><a href="#">B-1-3-2</a></li>
            <li class="depth-3"><a href="#">B-1-3-3</a></li>
            <li class="depth-2"><a href="#">B-1-4</a></li>
        </ul>
        <ul class="listCol3 megamenu">
            <li class="depth-3"><a href="#">B-1-4-1</a></li>
            <li class="depth-3"><a href="#">B-1-4-2</a></li>
            <li class="depth-3"><a href="#">B-1-4-3</a></li>
            <li class="depth-3"><a href="#">B-1-4-4</a></li>
            <li class="depth-3"><a href="#">B-1-4-5</a></li>
        </ul>
        <ul class="listCol4 megamenu">
            <li class="depth-2"><a href="#">B-1-5</a></li>
            <li class="depth-3"><a href="#">B-1-5-1</a></li>
            <li class="depth-3"><a href="#">B-1-5-2</a></li>
            <li class="depth-3"><a href="#">B-1-5-3</a></li>
            <li class="depth-3"><a href="#">B-1-5-4</a></li>
        </ul>
        <ul class="listCol5 megamenu last">
            <li class="depth-3"><a href="#">B-1-5-5</a></li>
        </ul>
    </div>
</li>

I've created the following process. Basically it loops through a gigantic unordered list with multiple level nested lists and creates a 2 level nested unordered list. It works well but is very slow in IE7. FireFox and Safari have no big problems with it. Not very good at jQuery I was wondering if I could speed up this by using better/faster/smarter functions. Due to the CMS I am using I can not change the output nor jQuery version I'm using which is 1.2.6.

Here's what I've got;

$('ul#mainnav li ul li').each(function() {
    // add level class
    $(this).addClass('depth-'+$(this).parents('ul').length);
    // make uls siblings in stead of children
    $($(this).children('ul')).insertAfter($(this));
});
// take all lis out of their uls
$('ul#mainnav li ul').each(function() {
    $(this).replaceWith($(this).children());                
});
// wrap chidlren lis with div
$('ul#mainnav li').each(function() {
    $(this).children('li:first').before('<ul class="megamenu" />');     
    $(this).children('.megamenu').append($(this).children('li'));
});
// apply plugin easyLisSplitter
$('.megamenu').easyListSplitter({ 
    colNumber: 5
});

Any ideas? If more info is needed let me know!

Cheers

EDIT:

Thanx for all the replies. Haven't tried everyting yet. Using var $this = $(this); sped up things by 20 milliseconds. Well I'll take those. All help is still welcome! Here's the before markup:

<ul id="mainnav">
<li><a href="#">A-1</a>
    <ul>
        <li><a href="#">A-1-1</a>
            <ul>
                <li><a href="#">A-1-1-1</a></li>
                <li><a href="#">A-1-1-2</a></li>
                <li><a href="#">A-1-1-3</a></li>
            </ul>
        </li>
        <li><a href="#">A-1-2</a></li>
        <li><a href="#">A-1-3</a>
            <ul>
                <li><a href="#">A-1-3-1</a></li>
                <li><a href="#">A-1-3-2</a></li>
                <li><a href="#">A-1-3-3</a></li>
            </ul>
        </li>
        <li><a href="#">A-1-4</a>
            <ul>
                <li><a href="#">A-1-4-1</a></li>
                <li><a href="#">A-1-4-2</a></li>
                <li><a href="#">A-1-4-3</a></li>
                <li><a href="#">A-1-4-4</a></li>
                <li><a href="#">A-1-4-5</a></li>
            </ul>
        </li>
        <li><a href="#">A-1-5</a>
            <ul>
                <li><a href="#">A-1-5-1</a></li>
                <li><a href="#">A-1-5-2</a></li>
                <li><a href="#">A-1-5-3</a></li>
                <li><a href="#">A-1-5-4</a></li>
                <li><a href="#">A-1-5-5</a></li>
            </ul>
        </li>
    </ul>
</li>
<li><a href="#">B-1</a>
    <ul>
        <li><a href="#">B-1-1</a>
            <ul>
                <li><a href="#">B-1-1-1</a></li>
                <li><a href="#">B-1-1-2</a></li>
                <li><a href="#">B-1-1-3</a></li>
            </ul>
        </li>
        <li><a href="#">B-1-2</a></li>
        <li><a href="#">B-1-3</a>
            <ul>
                <li><a href="#">B-1-3-1</a></li>
                <li><a href="#">B-1-3-2</a></li>
                <li><a href="#">B-1-3-3</a></li>
            </ul>
        </li>
        <li><a href="#">B-1-4</a>
            <ul>
                <li><a href="#">B-1-4-1</a></li>
                <li><a href="#">B-1-4-2</a></li>
                <li><a href="#">B-1-4-3</a></li>
                <li><a href="#">B-1-4-4</a></li>
                <li><a href="#">B-1-4-5</a></li>
            </ul>
        </li>
        <li><a href="#">B-1-5</a>
            <ul>
                <li><a href="#">B-1-5-1</a></li>
                <li><a href="#">B-1-5-2</a></li>
                <li><a href="#">B-1-5-3</a></li>
                <li><a href="#">B-1-5-4</a></li>
                <li><a href="#">B-1-5-5</a></li>
            </ul>
        </li>
    </ul>
</li>

And here's the after;

<ul id="mainnav">
<li><a href="#">A-1</a>
    <div class="listContainer1">
        <ul class="megamenu listCol1">
            <li class="depth-2"><a href="#">A-1-1</a></li>
            <li class="depth-3"><a href="#">A-1-1-1</a></li>
            <li class="depth-3"><a href="#">A-1-1-2</a></li>
            <li class="depth-3"><a href="#">A-1-1-3</a></li>
            <li class="depth-2"><a href="#">A-1-2</a></li>
        </ul>
        <ul class="listCol2 megamenu">
            <li class="depth-2"><a href="#">A-1-3</a></li>
            <li class="depth-3"><a href="#">A-1-3-1</a></li>
            <li class="depth-3"><a href="#">A-1-3-2</a></li>
            <li class="depth-3"><a href="#">A-1-3-3</a></li>
            <li class="depth-2"><a href="#">A-1-4</a></li>
        </ul>
        <ul class="listCol3 megamenu">
            <li class="depth-3"><a href="#">A-1-4-1</a></li>
            <li class="depth-3"><a href="#">A-1-4-2</a></li>
            <li class="depth-3"><a href="#">A-1-4-3</a></li>
            <li class="depth-3"><a href="#">A-1-4-4</a></li>
            <li class="depth-3"><a href="#">A-1-4-5</a></li>
        </ul>
        <ul class="listCol4 megamenu">
            <li class="depth-2"><a href="#">A-1-5</a></li>
            <li class="depth-3"><a href="#">A-1-5-1</a></li>
            <li class="depth-3"><a href="#">A-1-5-2</a></li>
            <li class="depth-3"><a href="#">A-1-5-3</a></li>
            <li class="depth-3"><a href="#">A-1-5-4</a></li>
        </ul>
        <ul class="listCol5 megamenu last">
            <li class="depth-3"><a href="#">A-1-5-5</a></li>
        </ul>
    </div>
</li>
<li><a href="#">B-1</a>
    <div class="listContainer2">
        <ul class="megamenu listCol1">
            <li class="depth-2"><a href="#">B-1-1</a></li>
            <li class="depth-3"><a href="#">B-1-1-1</a></li>
            <li class="depth-3"><a href="#">B-1-1-2</a></li>
            <li class="depth-3"><a href="#">B-1-1-3</a></li>
            <li class="depth-2"><a href="#">B-1-2</a></li>
        </ul>
        <ul class="listCol2 megamenu">
            <li class="depth-2"><a href="#">B-1-3</a></li>
            <li class="depth-3"><a href="#">B-1-3-1</a></li>
            <li class="depth-3"><a href="#">B-1-3-2</a></li>
            <li class="depth-3"><a href="#">B-1-3-3</a></li>
            <li class="depth-2"><a href="#">B-1-4</a></li>
        </ul>
        <ul class="listCol3 megamenu">
            <li class="depth-3"><a href="#">B-1-4-1</a></li>
            <li class="depth-3"><a href="#">B-1-4-2</a></li>
            <li class="depth-3"><a href="#">B-1-4-3</a></li>
            <li class="depth-3"><a href="#">B-1-4-4</a></li>
            <li class="depth-3"><a href="#">B-1-4-5</a></li>
        </ul>
        <ul class="listCol4 megamenu">
            <li class="depth-2"><a href="#">B-1-5</a></li>
            <li class="depth-3"><a href="#">B-1-5-1</a></li>
            <li class="depth-3"><a href="#">B-1-5-2</a></li>
            <li class="depth-3"><a href="#">B-1-5-3</a></li>
            <li class="depth-3"><a href="#">B-1-5-4</a></li>
        </ul>
        <ul class="listCol5 megamenu last">
            <li class="depth-3"><a href="#">B-1-5-5</a></li>
        </ul>
    </div>
</li>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

痴者 2024-10-03 17:06:56

另一件应该有所帮助的事情是通过将结果对象存储在变量中来消除冗余的 jquery 调用。例如,将以下内容更改

$('ul#mainnav li ul li').each(function() {
    // add level class
    $(this).addClass('depth-'+$(this).parents('ul').length);
    // make uls siblings in stead of children
    $($(this).children('ul')).insertAfter($(this));
});

为:

$('ul#mainnav li ul li').each(function() {
    var $this = $(this);
    // add level class
    $this.addClass('depth-'+$this.parents('ul').length);
    // make uls siblings in stead of children
    $($this.children('ul')).insertAfter($this);
});

请注意当引用 jquery 对象时,变量名称以 $ 开头的约定。

另外,我不确定,但我认为有一种更直接的方法来附加到子列表,这可能会简化上述代码的最后一行。也许像 $this.children('ul').append 之类的东西?

正如其他答案所说,只改变 live dom 一次。另一种方法是克隆您正在处理的整个结构,操作克隆,然后用克隆替换原始结构。无论您如何操作,关键是要避免浏览器尝试渲染所做的每个更改。

Another thing that should help is to eliminate redundant jquery calls by storing the resultant object in a variable. For example, change this:

$('ul#mainnav li ul li').each(function() {
    // add level class
    $(this).addClass('depth-'+$(this).parents('ul').length);
    // make uls siblings in stead of children
    $($(this).children('ul')).insertAfter($(this));
});

to this:

$('ul#mainnav li ul li').each(function() {
    var $this = $(this);
    // add level class
    $this.addClass('depth-'+$this.parents('ul').length);
    // make uls siblings in stead of children
    $($this.children('ul')).insertAfter($this);
});

Note the convention of starting a var name with $ when it refers to a jquery object.

Also, I'm not sure, but I think there's a more direct way to append to a list of children which might simplify the last line of the above code. Maybe something like $this.children('ul').append?

As the other answers say, only alter the live dom once. Another way to do this is to clone the whole structure that you're working on, manipulate the clone, and then replace the original with the clone. However you do it, the key is to avoid the browser trying to render each change as it's made.

向地狱狂奔 2024-10-03 17:06:56

您是否尝试在应用更改时隐藏列表,以避免浏览器在每次更改后重新排列布局?

Did you try hiding the list while applying the changes in order to save the browser from having to reflow the layout after each change?

§普罗旺斯的薰衣草 2024-10-03 17:06:56

您可以做的一件事是为您的 .megamenu 选择器提供上下文。按类名选择比按 id 选择需要更长的时间,因为 Javascript 中没有本地函数可以执行此操作。在选择器上设置范围有助于 jQuery 缩小对该类元素的搜索范围。它看起来像这样:

$('.megamenu', $('#someelement'))

但这在您的设置中可能是不可能的。

另一件事是构造一个 html 字符串,将其一次性附加到您的megamenu,而不是为列表中的每个 LI 运行append()。如果您想减少插入 DOM 节点所需的时间,jQuery 的追加方法非常适合处理大型 HTML 字符串。这似乎是这里最大的问题...您在循环内运行了大量 DOM 操作方法。您希望尽可能减少这些。然而,除了构造一个 html 字符串以一次将所有内容附加到 megamenu(可能应该是一个 ID,而不是一个类)之外,在您的脚本中可能无法做太多事情。

One thing you could do is provide a context for your .megamenu selector. Selecting by class name takes a bit longer than selecting by id because there's no native function to do it in Javascript. Setting a scope on the selector helps jQuery narrow the search for elements with that class. It would look like this:

$('.megamenu', $('#someelement'))

But it may not be possible in your setup.

Another thing would be to construct a string of html that you append to your megamenu all at once instead of running append() for each LI in your list. jQuery's append method works great with large HTML strings if you want to cut down on the time it takes to insert DOM nodes. That seems to be the biggest issue here...you're running a lot of DOM manipulation methods inside loops. You want to cut down on as many of these as you can wherever you can. It may not be possible to do much in your script, however, aside from constructing a string of html to append all at once to megamenu (which should, possibly, be an ID, not a class).

梦回梦里 2024-10-03 17:06:56

好吧,今晚我正在学习大量有关 jQuery 的知识...我尝试了一种完全不同的方法。我想要第二级及更深层次的所有列表项作为兄弟姐妹的原因是因为我想使用 easylistsplitter 插件。因为这消耗了大量资源,所以我创建了以下代码。我真的不需要列表项,Google 不运行 jQuery,所以它会看到列表项,我的用户将看到一个整洁的小菜单,菜单项分为几列。希望这段代码对其他人有帮助,它只用了第一个代码一半的时间即可完成工作。

如果有人有任何关于使此代码更快的指示,请告诉我。

    $('ul#mainnav).each(function() {
    $(this).children('li').append('<div class="megamenu" />');
});
$('ul#mainnav').each(function() {
    var $this = $(this);
    var $length = $this.parents('ul').length;
    $this.addClass('depth-'+$length);
    if($length > 1) {
        $this.appendTo($this.parents('li').find('div.megamenu'));
    }
});
$('ul#mainnav ul').remove();
$('ul#mainnav div.megamenu').each(function() {
    var links = $(this).find('a');
    var columns = 5;
    var perCol = Math.ceil(links.length/columns);
    for(var i = 0; i < links.length; i+=perCol) { 
      links.slice(i, i+perCol).wrapAll('<div>'); 
    }
});

Well I'm learning loads about jQuery tonight... I have tried a completely different approach. The reason I wanted all list items of 2nd level and deeper as siblings is because I wanted to use the easylistsplitter plugin. Because this ate a lot of the resources I created the following code. I don't really need list items, Google doesn't run jQuery so it will see list items, my users will see a neat little menu with menu items split into columns. Hope this code helps others, it does the job in half the time of the first code.

If anyone has any pointers on making this code even faster please let me know.

    $('ul#mainnav).each(function() {
    $(this).children('li').append('<div class="megamenu" />');
});
$('ul#mainnav').each(function() {
    var $this = $(this);
    var $length = $this.parents('ul').length;
    $this.addClass('depth-'+$length);
    if($length > 1) {
        $this.appendTo($this.parents('li').find('div.megamenu'));
    }
});
$('ul#mainnav ul').remove();
$('ul#mainnav div.megamenu').each(function() {
    var links = $(this).find('a');
    var columns = 5;
    var perCol = Math.ceil(links.length/columns);
    for(var i = 0; i < links.length; i+=perCol) { 
      links.slice(i, i+perCol).wrapAll('<div>'); 
    }
});
聽兲甴掵 2024-10-03 17:06:56

您是否尝试过对以前版本的 jQuery 使用 .detach() 类似的解决方法(因为 detach 是 1.4具体的)?

具体来说这个例子可能有效(不确定,我不再使用1.2.6请求者要求提供 1.3.2 解决方法)。

elem.clone(true);
elem.remove(); 

Have you tried using the .detach() -alike workarounds for previous versions of jQuery (since detach is 1.4 specific)?

Specifically this example might work (not sure, I don't use 1.2.6 anymore and the requester asked for a 1.3.2 workaround).

elem.clone(true);
elem.remove(); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文