简体   繁体   English

最小化jquery.append重站点的DOM访问

[英]Minimizing DOM access for jquery.append heavy site

Here's a bit of code that represents the general style I've been coding my site: 以下是一些代码,这些代码代表了我一直在为网站编写的一般样式:

!function(){
    window.ResultsGrid = Class.extend(function(){

        this.constructor = function($container, options){
            this.items = [];
            this.$container = $($container);
            this.options = $.extend({}, defaultOptions, options);

            this.$grid = $(
                '<div class="results-grid">\
                    <ul></ul>\
                </div>'
            )
                .css("margin", -this.options.spacing / 2);

            this.$list = this.$grid.find("ul");

            this.$container.append(this.$grid);
        };


        this.setItems = function(datas) {
            this.$grid.addClass("display-none");
            this.clear();
            for (var k in datas) this.addItem(datas[k]);
            this.$grid.removeClass("display-none");
        };

        this.addItem = function(data) {
            var width = this.options.columnWidth;
            var height = this.options.rowHeight;
            var padding = this.options.spacing / 2;
            if (this.options.columns > 0) width = (this.$container.width() - this.options.columns * this.options.spacing) / this.options.columns;
            if (this.options.rows > 0) height = (this.$container.height() - this.options.rows * this.options.spacing) / this.options.rows;
            if (this.options.ratio > 0) height = width / this.options.ratio;
            var item = new (this.options.class)(this.$list, {
                data: data,
                type: this.options.type,
                width: width,
                height: height,
                padding: padding
            });
            this.items.push(item);
        };

        this.clear = function() {
            for (var k in this.items) this.items[k].destroy();
            this.items.length = 0;
        };

        this.destroy = function() {
            this.clear();
            this.$grid.find("*").off();
            this.$grid.remove();
        }
    });

    var defaultOptions = {
        class: ResultsItem.Game,
        type: ResultsItem.Game.COMPACT,
        columns:1,
        rows:0,
        spacing: 10,
        rowHeight: 80,
        ratio: 0,
        columnWidth: 0
    };

}();

This is something I use for lists of items, it's just a base class so it looks fairly pointless. 这是我用于项目列表的东西,它只是一个基类,因此看起来毫无意义。 On my homepage I have a few of these 'ResultsGrids' and in total I have about 100 items to be added. 在我的主页上,有一些“ ResultsGrids”,总共有大约100个项目要添加。 Each of these items calls append, addClass, css, etc. to their representative jquery object about 5 times, so that's a lot of HTML fiddling before it ever renders. 这些项目中的每一个都向它们的代表性jquery对象调用append,addClass,css等大约5次,因此在渲染之前,很多HTML都在摆弄。 Problem is, there's quite a noticable time delay as I've just come to understand I'm accessing the DOM an unnecessary amount of times by calling methods like jquery.append for each item. 问题是,有一个明显的时间延迟,因为我刚开始了解我通过为每个项目调用诸如jquery.append之类的方法来不必要地访问DOM。

The obvious solution is to do one big append for each ResultsGrid by concatenating the html strings of each item, but I wonder if there's a middle ground between this and my current approach which will perform just as well, otherwise I'll have to rewrite a lot of code. 显而易见的解决方案是通过串联每个项目的html字符串为每个ResultsGrid进行一个大追加,但是我想知道在此方法和我的当前方法之间是否有中间立场,同样可以执行,否则我将不得不重写一个很多代码。

I like to start with a $("") and append bit by bit, but obviously this isn't good performance wise because it's constantly recalculating stuff, but I don't need to know the width, height and position of everything every step of the way. 我喜欢从$(“”)开始并逐位追加,但是显然这并不是很好的性能,因为它会不断地重新计算内容,但是我不需要知道每一步的宽度,高度和位置的方式。 Ideally I'd like to tell it to not do anything to the DOM until I tell it to. 理想情况下,我想告诉它在我告诉它之前不要对DOM做任何事情。 If there's no way to do this with jquery, then I'd like a library that will allow me to do this. 如果没有办法用jquery做到这一点,那么我想要一个可以让我做到这一点的库。 I've had a brief look at js templating libraries but they don't look very enticing. 我对js模板库进行了简要介绍,但它们看起来并不很诱人。 Angular especially. 尤其是有角度的。

I don't have the big picture of what you're trying to do, but, from what I understand, you could try using jquery's $.detach() function. 我没有您打算做什么的大图片,但是,据我了解,您可以尝试使用jquery的$.detach()函数。

this.setItems = function(datas) {
            //store the parent of this grid                
            this.parent = this.$grid.parent();
            this.$grid.detach();
            this.$grid.addClass("display-none");
            this.clear();

            //here you add your html/etc to the grid
            for (var k in datas) this.addItem(datas[k]);

            //reattach the grid to the parent
            this.parent.append(this.$grid);
            this.$grid.removeClass("display-none");
        };

Doing DOM manipulation on detached elements should be much faster and provide you with an in-between solution like you were thinking. 对分离的元素进行DOM操作应该更快,并且可以像您所想的那样为您提供介于中间的解决方案。 This is a performance tip that you could find here , along with some other useful ones. 这是一个性能技巧,您可以在这里找到它,以及其他一些有用的技巧。

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

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