web-dev-qa-db-ja.com

JavaScript DOM操作後のInternet ExplorerでのDOM更新の強制

これが状況です。次のようなJavaScriptがあります。

function onSubmit() {
    doSomeStuff();
    someSpan.style.display="block";
    otherSpan.style.display="none";
    return doLongRunningOperation;
}

これをフォーム送信アクションにして、非IEブラウザから実行すると、2つのスパンの可視性がすばやく入れ替わり、長いJavaScript操作が実行されます。これをIE onSubmit()が完全に戻るまでスワップを行いません。

次のように警告ボックスを貼り付けることで、domを強制的に再描画できます。

function onSubmit() {
    doSomeStuff();
    someSpan.style.display="block";
    otherSpan.style.display="none";
    alert("refresh forced");
    return doLongRunningOperation;
}

また、明らかなjqueryリファクタリングはIE動作に影響しません:

function onSubmit() {
    doSomeStuff();
    $("#someSpan").show();
    $("#otherSpan").hide();
    return doLongRunningOperation;
}

この動作はIE8およびIE6に存在します。これらのブラウザでDOMを強制的に再描画する方法はありますか?

27
Justin Dearing

LongRunningOperationを非同期で呼び出すことはできますか?

2
misteraidan

Mozilla(たぶんIEも同様)は、表示に影響するDOMへの実行中の変更をキャッシュ/遅延するため、すべての変更を一度にすべてのステートメントの後に繰り返し計算するのではなく、一度に計算できます。

更新を強制するには(即時の同期リフローまたは再レイアウトを強制するため)、JavaScriptは変更の影響を受けるプロパティを読み取る必要があります。 someSpanおよびotherSpanの場所。

(このMozilla実装の詳細はビデオで言及されています Fast HTML and CSS:Layout Engine Internals for Web Developers 。)

17
ChrisW

ChrisWの発言を続けるには:

ここではフラッシュDOMにスクリプトをフラッシュしているので、alert( "");を呼び出す必要はありません。 ( http://amolnw.wordpress.com/category/programming/javascript/ にあります):

function flushThis(id){
   var msie = 'Microsoft Internet Explorer';
   var tmp = 0;
   var elementOnShow = document.getElementById(id);
   if (navigator.appName == msie){
      tmp = elementOnShow.parentNode.offsetTop  +  'px';
   }else{
      tmp = elementOnShow.offsetTop;
   }
}

それは私のために働きます!!!ヒントをありがとう。

8
OKL

Chrome 21で、ディセンダー( 'g')の文字が含まれているWordをドラッグすると、この問題が発生しました。画面に蛾の塵の跡が残り、次の行が消えます。何かが画面を更新したとき、ChrisWのソリューション(レイアウトに依存するプロパティの問い合わせ)が機能しませんでした。

うまくいったのは、ページの上部に1ピクセルの空白のdivを追加し、それから1ミリ秒後にそれを削除するために、ドラッグ操作の最後に次の関数を呼び出すことでした。

// Needed by Chrome, as of Release 21. Triggers a screen refresh, removing drag garbage.
function cleanDisplay() {
    var c = document.createElement('div');
    c.innerHTML = 'x';
    c.style.visibility = 'hidden';
    c.style.height = '1px';
    document.body.insertBefore(c, document.body.firstChild);
    window.setTimeout(function() {document.body.removeChild(c)}, 1);
}

注:遅延が必要です。単にdivを追加および削除するだけでは機能しません。また、divは、ページの再描画が必要な部分の上に追加する必要があります。

5
George

長期関数をsetTimeout(function(){longTerm();}、1);でラップすることもできます。

3
Konrad

element.focus()はIE10で機能します

function displayOnOff(){
    var Elm = document.getElementById("myDiv");
    Elm.style.display="block";
    Elm.focus();
    for(var i=0; i<1000000; i++){
        console.log("waiting...............");
    }
    Elm.style.display = "none";
}
2
nilesh bhaumik