【问题标题】:Will chaining jquery add class method trigger multiple reflows?链接jquery添加类方法会触发多个回流吗?
【发布时间】:2014-07-10 00:06:27
【问题描述】:

我想知道链接 jquery 函数是否会触发多次重排,或者重排是否在语句结束后仅发生一次。

$('label[hierarchyName="' + toolbarStatus.Years[i] + '"]').addClass('active').addClass('btn-success');

任何意见表示赞赏。谢谢。

【问题讨论】:

  • 不是回流专家。不过,我只想指出,您可以通过 .addClass('active btn-success') 同时添加两个类。
  • 我认为回流发生在链中的每个函数上,因为它们按照它们被链接的顺序执行。试试.addClass('active btn-success');
  • 是的,你可以通过在你的案例中链接来访问所有这些元素,你可以通过一个简单的测试自己找到答案......
  • 我认为这可能取决于浏览器..因为浏览器可能会将回流延迟几毫秒以进行性能优化,在这种情况下它可能只会导致一次回流..

标签: jquery css optimization reflow


【解决方案1】:

可能触发多次回流,但实际上不会。

当 CSS 样式按顺序更改时,所有现代浏览器都会通过将所有更改合并为一个来优化流程,然后执行重排。

(这可能会引起注意,并且在链接有意义的情况下可能会非常烦人,例如在另一个之前添加 no-transition 类时......在这些情况下,您必须依靠不一致的黑客来强制重排/重绘)

【讨论】:

    【解决方案2】:

    它会触发多次回流。链接就像在单个选择器上应用多个方法一样。每次添加一个类时,它都会重新生成 DOM 并呈现它..

    示例在 JSFiddle 上给出。 - http://jsfiddle.net/5kkCh/

    就像

    var obj = {
        first: function() { alert('first'); return obj; },
        second: function() { alert('second'); return obj; },
        third: function() { alert('third'); return obj; }
    }
    
    obj.first().second().third();
    

    这里是 jQuery 的 addClass 函数

    addClass: function( value ) {
        var classes, elem, cur, clazz, j, finalValue,
            i = 0,
            len = this.length,
            proceed = typeof value === "string" && value;
    
        if ( jQuery.isFunction( value ) ) {
            return this.each(function( j ) {
                jQuery( this ).addClass( value.call( this, j, this.className ) );
            });
        }
    
        if ( proceed ) {
            // The disjunction here is for better compressibility (see removeClass)
            classes = ( value || "" ).match( rnotwhite ) || [];
    
            for ( ; i < len; i++ ) {
                elem = this[ i ];
                cur = elem.nodeType === 1 && ( elem.className ?
                    ( " " + elem.className + " " ).replace( rclass, " " ) :
                    " "
                );
    
                if ( cur ) {
                    j = 0;
                    while ( (clazz = classes[j++]) ) {
                        if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
                            cur += clazz + " ";
                        }
                    }
    
                    // only assign if different to avoid unneeded rendering.
                    finalValue = jQuery.trim( cur );
                    if ( elem.className !== finalValue ) {
                        elem.className = finalValue;
                    }
                }
            }
        }
    
        return this;
    }
    

    如果您看到 for 循环,它会在每次调用 addClass 时更新类名(附加到现有类)...

    如果你参考 stubbornella (http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/) 写的文章,更改 className 会导致回流..

    我希望能解释 :-)

    【讨论】:

    • @Pazza22 & Rahul:仅仅因为函数是串行运行的,并不意味着浏览器一定会在添加类时立即进行重排。
    • 我同意。但我只是在谈论 jQuery Chaining 是如何工作的。 :-)
    • @RahulPatil:嗯,问题是关于回流的。回答有关链接并不能回答有关回流的问题(尽管上面有 Pazza 的评论)。再说一遍:我会假设在添加类时会立即发生回流。这不会是一个非常优化的实现,现代浏览器已经非常优化。
    • @T.J 我基本上假设回流会发生多次,因为问题中的代码不完全是一个语句(如 Rahul 所示)。但是在经历了一些 cmets 之后,我的印象是它依赖于浏览器并且可能只发生一次。但是,我将结合这两个 .addClass() 只是为了更安全。谢谢大家:)
    • @T.J.Crowder 和@Pazza22 .. 我在上面的答案中添加了简短的解释,我希望能解释:D
    猜你喜欢
    • 2020-10-13
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    • 2011-06-06
    • 1970-01-01
    • 2015-03-02
    相关资源
    最近更新 更多