How to filter a very large bootstrap table using pure Javascript

前端 未结 7 2256
清歌不尽
清歌不尽 2021-02-05 12:05

I\'ve built a large table in bootstrap, about 5,000 rows x 10 columns, and I need to filter the table for specific attributes, fast, using only JavaScript. The table has both an

7条回答
  •  花落未央
    2021-02-05 12:57

    Your best option is to not render all those things and store object versions of them and only show a max of 50 rows at a time via pagination. Storing that many objects in memory, in JS is no problem. Storing all of those in DOM on the other hand will bring browsers to their knees. 5000 is at around the upper bound of what a browser can do on a good machine while maintaining decent performance. If you start modifying some of those rows and tweaking things ('hiding', 'showing') things definitely will get even slower.

    The steps would look something like:

    1. Organize the data into an array of objects, your hash map is great for supplementary and quick access purposes.
    2. Write some sorting and filtering functions that will give you the subsets of data you need.
    3. Write a paginator so you can grab sets of data and then get the next set based on some modified params
    4. Replace your "draw/render" or "update" method with something that displays the current set of 50 that meets the criteria entered.

    The following code should be considered pseudo code that probably works:

    // Represents each row in our table
    function MyModelKlass(attributes) {
        this.attributes = attributes;
    }
    
    // Represents our table
    function CollectionKlass() {
        this.children = [];
        this.visibleChildren = [];
        this.limit = 50;
    }
    
    CollectionKlass.prototype = {
        // accepts a callback to determine if things are in or out
        filter: function(callback) {
            // filter doesn't work in every browser
            // you can loop manually or user underscorejs
            var filteredObjects = this.children.filter(callback);
    
            this.visibleChildren = filteredObjects;
            this.filteredChildren = filteredObjects;
            this.showPage(0);
        },
        showPage: function(pageNumber) {
            // TODO: account for index out of bounds
            this.visibleChildren = this.filteredChildren.slice(
               pageNumber * this.limit,
               (pageNumber + 1) * this.limit
            );
        },
        // Another example mechanism, comparator is a function
        // sort is standard array sorting in JS
        sort: function(comparator) {
            this.children.sort(comparator);
        }
    }
    
    function render(el, collection, templateContent) {
        // this part is hard due to XSS
        // you need to sanitize all data being written or
        // use a templating language. I'll opt for 
        // handlebars style templating for this example.
        //
        // If you opt for no template then you need to do a few things.
        // Write then read all your text to a detached DOM element to sanitize
        // Create a detached table element and append new elements to it
        // with the sanitized data. Once you're done assembling attach the
        // element into the DOM. By attach I mean 'appendChild'.
        // That turns out to be mostly safe but pretty slow. 
        //
        // I'll leave the decisions up to you.
        var template = Handlebars.compile(templateContent);
        el.innerHTML(template(collection));
    }
    
    // Lets init now, create a collection and some rows
    var myCollection = new CollectionKlass();
    
    myCollection.children.push(new MyModelKlass({ 'a': 1 }));
    myCollection.children.push(new MyModelKlass({ 'a': 2 }));
    
    // filter on something...
    myCollection.filter(function(child) {
        if (child.attributes.a === 1) {
            return false;
        }
    
        return true;
    });
    
    // this will throw an out of bounds error right now
    // myCollection.showPage(2); 
    
    // render myCollection in some element for some template
    render(
        document.getElementById('some-container-for-the-table'), 
        myCollection,
        document.getElementById('my-template').innerHTML()
    );
    
    // In the HTML:
    
    
    

提交回复
热议问题