Firstly, the demo. I’ve got 100,000 items, quite a hefty data set, which is randomly generated in a function. You can change the number of items easily in the JS area. Click on the + or – icons to expand or collapse nodes.
It’s still quick, like instant, with 100,000 items. It can start to slow a little at a million but I’d say it’s still acceptable given that kind of data.
One Long List
The trick is in how the data is structured. It’s one big array, not hierarchical data with objects inside other objects. The reason for this is pretty simple, it’s all about iterations or looping. If you have a single array you can run through the whole list of items once. If it’s nested you have to get into loops inside other loops and it gets more complicated and takes longer. In fact, you’d be lucky for it to work at all without getting stack overflow errors.
I use map() to convert each data item into a HTML list item which I can insert into the DOM. I use filter() to quickly find the children items of any item by returning a subset, and I use some() to see if an item has children. The beauty of some() is that once its found it child it stops iterating, saving time.
Easy on the DOM
The other part of this is keeping DOM manipulation to a minimum. Playing around with data in memory trivial for a browser but making changes to the DOM and rendering things on screen takes time. So, only the nodes that are needed right now exist in the DOM – there are not hidden items waiting on the sidelines. So, a new <ul> is added when you expand a node and the <ul> is removed when you collapse. A + icon is shown if the item has children of its own but we don’t know anything about how many it has or what they contain until it’s expanded.