简体   繁体   中英

Performance with jQuery .nextUntil on large DOM

I'm looking to address a performance issue I'm having with a very large DOM. In essence, this a word-processing style app inside the browser using contenteditable divs .

Suppose I have a structure like this:

<div class="header">...</div>
<div class="actor">...</div>
<div class="director">...</div>
<div class="producer">...</div>
<div class="writer">...</div>
<div class="executive">...</div>
<div class="studio">...</div>
<div class="footer">...</div>

I then have some code which ends up returning (for example):

<div class="writer">...</div>

as a jQuery object. I then need to retrieve all of this object's surrounding divs between header and footer as a selection and then further filter this list using a class eg 'actor' .

Currently, I have the following code, which works correctly:

// Find header
var header_object = object.prevUntil(".header").last().prev();

// Select all objects between header and footer, and then filter 
var object_list = header_object.nextUntil(".footer", ".actor");

// Iterate through object_list 
object_list.each(function()
{
    // Run additional code on the objects
});

The only problem is that due to the app being a word processor of sorts, the DOM structure is often very large (eg over 5000 elements) and executing this code locks up the browser for an unacceptable amount of time (over 10 - 30 seconds).

As such, I'm looking for a way to customize the code I have to make it more efficient / improve performance.

I should also point out that the HTML structure above is not (header - 5000 elements - footer) , rather it is 200 x (header - elements - footer) . As such, each traversal operation is only maybe 25 elements from header to footer, but it has to run many times.

Any suggestions? Many thanks!

You could enhance performance by not using jQuery, and creating your own functions that are more specific to your use case.

function getClosest(el, klass, dir) {
    while (el && (!el.classList.contains(klass))) {
        el = el[dir ? 'previousElementSibling' : 'nextElementSibling'];
    }
    return el;
}

function getbetween(from, to, filterKlass) {
    var list = [];
    while(from && to && from !== to) {
        if ((from = from.nextElementSibling) !== to) {
            filterKlass ? (from.classList.contains(filterKlass) ? list.push(from) : Infinity) : list.push(from);
        } 
    }
    return list;
}

var object  = $('.writer');
var element = object.get(0);

var header_object = getClosest(element, 'header', true);
var footer_object = getClosest(element, 'footer', false);
var object_list   = getbetween(header_object, footer_object, 'actor');

object_list.forEach(function(element) {
    console.log(element);
});

FIDDLE

Traversing the next element sibling directly, and checking for classes, should be much faster than using nextUntil

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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