2017-01-03 8 views
4

私は小さなJavaScriptのテンプレートエンジンに取り組んでいます、と私はモデルが変更されたときにDOMへの更新を扱うための2つの可能なアプローチがあります:DOMの更新が実際にそれを実行する前に、必要な場合DOMに触れると、何も変わらなくてもリフローと再描画がトリガされますか?

  1. チェックを。これは不必要な更新を危険にさらさないという利点がありますが、私は古い値を追跡するスペースを無駄にしています。

    if (oldValue !== newValue) { 
        element.textContent = newValue; 
    } 
    
  2. ちょうどそれを行います。これは明らかに簡単ですが、私は何の理由もなく再塗装とリフローを引き起こすのではないかと恐れています。私もsetAttributeaddClassremoveClassを呼び出し、プラスstyle[prop] = valueを設定することで、DOMを操作しています

    element.textContent = newValue; 
    

注意。

私の質問は、実際に何も変更せずにDOMをタッチすると、現代のブラウザは実際に変更されていないことに気付き、リフローまたは再描画を実行しないことに気付くでしょうか?

+2

現在のところ、ブラウザは非常にスマートです。変化がなければリフローは起こらず、賢明に表示されます。その場合でも、再描画は影響を受ける画面の部分にのみ適用されます。 –

+0

*私はスペースを無駄にしています*はい、スペースは最近の保険料になります、私のデスクトップは32GBのRAMしか持っていません。 –

+1

@ torasaburo大規模なSPAのすべてのバインドされた値のコピーを保持することは、モバイルデバイスでは高価です。頻繁に変更すると、収集する必要があるゴミがたくさん生成され、フレームレートが狂ってしまいます。それは大きな効果ではありませんが、それを行う際にゼロ点がある場合、まだここで勝つために何かがあるかもしれません。 – Anders

答えて

3

MutationObserver apiを使用すると、DOMの変更を検出できます。

ここでは、ブラウザが希望の内容に基づいてDom Changedイベントをトリガーするかどうかを確認するための例を示します。

ここでは、jqueryのtext('...')と、jqueryを使用しないel.textContentの両方があります。クロム55で

$(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>

  • 、のみsetAttribute()とjQuery text()Dom Changeイベントをトリガしました。
  • Firefox 50では、すべてがDom Changeイベントをトリガーしました。
  • Edge 38では、すべてがDom Changeイベントをトリガーしました。
+1

クールな答え!私はいくつかの結果を更新しました。 1つの考え:いいえドームチェンジイベントは再描画/リフローを意味しません。しかし、DOMの変更イベントは再描画/リフローを意味するのでしょうか? – Anders

+1

'repaint/reflow'に関して - 私は本当にそれについてはまだわかっていませんが、ここでは試してみることができます - たくさんのテキストを持つ要素を取ってください(1Mの文字で始まり、 )、 '$(el).text($(el).text())'を使います。それはjQueryによるのでDOMをトリガーします - ブラウザーがこれを行うために時間/ CPU /スクロールの変更を取るかどうかを確認してください。 – Dekel

+1

FFでいくつかのテストを行ったところ、パフォーマンスモニタが再描画してリフローするタイミングを知らせることが判明しました。小文字(1K文字)の場合は、時折再描画をトリガしますが、リフローは行いません。大文字(1M文字)の場合、毎回高価なリフローと再描画が発生します。 – Anders

関連する問題