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

Posted

技术标签:

【中文标题】最小化 jquery.append 重站点的 DOM 访问【英文标题】:Minimizing DOM access for jquery.append heavy site 【发布时间】:2015-09-30 21:56:24 【问题描述】:

这里有一段代码代表了我编写网站的一般风格:

!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
    ;

();

这是我用于项目列表的东西,它只是一个基类,所以看起来毫无意义。 在我的主页上,我有一些这样的“ResultsGrids”,总共有大约 100 项要添加。这些项目中的每一个都对其代表的 jquery 对象调用 append、addClass、css 等大约 5 次,因此在呈现之前需要进行大量的 html 摆弄。 问题是,有一个相当明显的时间延迟,因为我刚刚明白我通过为每个项目调用 jquery.append 之类的方法来访问 DOM 的次数是不必要的。

显而易见的解决方案是通过连接每个项目的 html 字符串为每个 ResultsGrid 做一个大附加,但我想知道这和我当前的方法之间是否有一个中间立场,它会表现得一样好,否则我会有重写很多代码。

我喜欢从 $("") 开始并一点一点地追加,但显然这在性能方面并不好,因为它不断地重新计算东西,但我不需要知道宽度、高度和位置每一步的一切。理想情况下,我想告诉它在我告诉它之前不要对 DOM 做任何事情。如果无法使用 jquery 执行此操作,那么我想要一个允许我执行此操作的库。 我已经简要了解了 js 模板库,但它们看起来并不是很诱人。尤其是 Angular。

【问题讨论】:

我在您包含的代码中只看到一个.append(),因此很难理解您要修复哪些.append() 操作。 【参考方案1】:

我不知道你想要做什么,但据我了解,你可以尝试使用 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");
        ;

对分离的元素进行 DOM 操作应该会更快,并为您提供如您所想的中间解决方案。 这是一个性能提示,您可以找到 here,以及其他一些有用的提示。

【讨论】:

当一个 jq 对象被分离时,它仍然链接到一个 Dom 片段,当它被改变时,它会重新计算尺寸等等,对吧?我想知道是否有一个库可以让我一点一点地创建 dom 元素,但无需接触 dom 或做任何无关的工作(直到我最终想将它添加到 dom 中) 分离时,元素不链接到 DOM,jquery 处理所有更改并且速度更快,因为 DOM 不需要在每次修改时更新其所有结构。您使用 jquery 所做的已经在 DOM 之外创建元素,相当于 document.createElement(),只有当您将项目附加到另一个 DOM 元素时,它才会“触及”DOM。 啊,现在明白了(我想)。我被误解所困扰。一些快速测试表明,分离节省了大量时间,谢谢!

以上是关于最小化 jquery.append 重站点的 DOM 访问的主要内容,如果未能解决你的问题,请参考以下文章

jquery append的 class失效

jQuery .append() :奇怪的行为

.append 之后的 jQuery 函数

jquery append方法加标签class失效

js原生怎么做到jquery append方法的效果

Jquery .append 重写