即使没有任何变化,触摸DOM触发回流和重绘吗? [英] Does touching the DOM trigger a reflow and repaint even if nothing changes?

查看:136
本文介绍了即使没有任何变化,触摸DOM触发回流和重绘吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


    我正在研究一个小型JavaScript模板引擎,并且我有两种可能的方法来处理模型更改时DOM的更新:
  1. 在执行之前检查DOM更新是否真的需要。这有利于避免不必要的更新,但我浪费空间来跟踪旧值。

      if(oldValue! == newValue){
    element.textContent = newValue;
    }


  2. 只要做到这一点。这显然比较简单,但我恐怕会触发重新绘制并无故重新流回。

      element.textContent = newValue ; 


请注意,我也在操纵DOM调用 setAttribute addClass removeClass ,再加上 style [prop] = value



所以,我的问题是:现代浏览器是否足够聪明, ,并且因此不运行重排或重绘,如果你触摸DOM而没有实际改变任何东西?

使用 MutationObserver api 您可以检测到 DOM 更改。



以下示例可用于查看浏览器是否触发 Dom Changed 事件,基于你想要的。



这里有一个文本('... ')由jquery和 el.textContent (不使用jquery)。



  $(document).ready(function(){$('#btn1')。click(function(){console.log('text changed  -  jquery'); $('#a1')。text('text 1'); }); $('#btn2')。click(function(){console.log('text changed  -  textContent'); $('#a1')[0] .textContent = $('#a1')[0]。 textContent}); $('#btn3')。click(function(){console.log('class changed'); $('#a1')。attr('class','cls'+ Math.floor(Math.random )* 10));});}); var target = $('#a1')[0]; //创建一个观察者instancevar observer = new MutationObserver(function(mutations){var changed = false; mutations.forEach (function(mutation){//你可以在这里查看实际的变化}); console.log('Dom Changed');}); //配置观察者:var config = {attributes:true,childList:true, characterData:true}; //传入目标节点以及observer optionsobserver.observe(target,config);  

  .cls1 {border:1px solid red;}。cls2 {border:1px solid pink;}。cls3 {border:1px solid cyan;}。cls4 {border: cls5 {border:1px solid orange;}。cls5 {border:1px solid dark;}。cls8 {border:1px solid black;}。cls8 {border:1px solid yellow;}。cls9 {border: 1px固体蓝色;}。cls10 {border:1px solid green;}  

< script src =https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js>< / script>< div id =a1class = cls1>文字1< / div>< button id =btn1>更改文字 - jquery(保留原文)< / button>< br />< button id =btn2>更改文本 - textContent(保留原文)< / button>< br />< button id =btn3>更改类别(实际更改)< /按钮> setAttribute()

code>和jQuery text()触发了 Dom Change 事件。
  • 在Firefox 50中,所有内容都触发了 Dom Change 事件。

  • 在Edge 38中,所有内容都触发了 Dom Change 事件。


  • I am working on a small JavaScript template engine, and I have two possible approaches for dealing with updates to the DOM when the model changes:

    1. Check if the DOM update is really needed before doing it. This has the benefit of not risking unnecessary updates, but I am wasting space on keeping track of old values.

      if (oldValue !== newValue) {
          element.textContent = newValue;
      }
      

    2. Just do it. This is obviously simpler, but I am afraid that I will be triggering repaints and reflows for no reason.

      element.textContent = newValue;
      

    Note that I am also manipulating the DOM by calling setAttribute, addClass and removeClass, plus setting style[prop] = value.

    So, my question is: Are modern browsers smart enough to notice that nothing actually changed, and therefore not run reflow or repaint, if you touch the DOM without actually changing anything?

    解决方案

    Using the MutationObserver api you can detect DOM changes.

    Here is an example you can use to see if a browser triggers the Dom Changed event, based on what you want.

    You have here both a text('...') by jquery and an el.textContent (that doesn't use jquery).

    $(document).ready(function() {
      $('#btn1').click(function() {
        console.log('text changed - jquery');
        $('#a1').text('text 1');
      });
      $('#btn2').click(function() {
        console.log('text changed - textContent');
        $('#a1')[0].textContent  = $('#a1')[0].textContent 
      });
      $('#btn3').click(function() {
        console.log('class changed');
        $('#a1').attr('class', 'cls' + Math.floor(Math.random() * 10));
      });
    });
    
    
    var target = $('#a1')[0];
    
    // create an observer instance
    var observer = new MutationObserver(function(mutations) {
      var changed = false;
      mutations.forEach(function(mutation) {
        // You can check the actual changes here
      });
      console.log('Dom Changed');
    });
    
    // configuration of the observer:
    var config = { attributes: true, childList: true, characterData: true };
    
    // pass in the target node, as well as the observer options
    observer.observe(target, config);

    .cls1 {
      border: 1px solid red;
    }
    .cls2 {
      border: 1px solid pink;
    }
    .cls3 {
      border: 1px solid cyan;
    }
    .cls4 {
      border: 1px solid darkgreen;
    }
    .cls5 {
      border: 1px solid orange;
    }
    .cls6 {
      border: 1px solid darkred;
    }
    .cls7 {
      border: 1px solid black;
    }
    .cls8 {
      border: 1px solid yellow;
    }
    .cls9 {
      border: 1px solid blue;
    }
    .cls10 {
      border: 1px solid green;
    }

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="a1" class="cls1">text 1</div>
    <button id="btn1">Change text - jquery (keep original)</button><br />
    <button id="btn2">Change text - textContent (keep original)</button><br />
    <button id="btn3">Change class (real change)</button>

    • In Chrome 55, only setAttribute() and jQuery text() triggered the Dom Change event.
    • In Firefox 50, everything triggered the Dom Change event.
    • In Edge 38, everything triggered the Dom Change event.

    这篇关于即使没有任何变化,触摸DOM触发回流和重绘吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆