3

定期的に div の表示を切り替える必要があるページがあります。問題は、親要素の 1 つに関連するクリック イベントが呼び出されないことが多いことです。表示切り替えを停止するか、速度を落とすと (たとえば、100 ミリ秒ではなく 300 ミリ秒)、クリック イベントが正常に発生します。

この問題を説明する短い例を作成しました。ここでテストできます: http://threeds.me/0xC0DE/

青/赤の四角形をクリックすると、理論上はクリック イベントが発生します。アニメーションがない場合 (ここではデフォルトの動作)、青い四角をクリックすると、常に onclick イベントが発生します。「再生/一時停止」をクリックすると、赤い四角の可視性が 100 ミリ秒ごとに切り替わり始めます。アニメーションの再生中、四角をクリックするたびにクリック イベントが呼び出されるわけではありません。

可視性を変更すると、何らかの形でDOMが台無しになり、その結果、イベントが数ミリ秒間停止すると思われます。ページへの影響を最小限に抑えるために css の表示プロパティを切り替えようとしましたが、結果は同じでした。

しかし、イベントだけではありません。コンテナ全体をタグにカプセル化すると、要素をクリックしてもブラウザで常に考慮されるとは限りません。したがって、子要素の可視性を変更すると、親が(かなり)しばらくの間盲目になるようです。これは本当に奇妙だと思います。

この問題は、Firefox、Chrome、および Opera (すべて mac 上でテストできない) と一致しているため、取得できないものがあることを意味します。ですから、解決策が得られなくても、何が問題なのかを理解したいと思います。

すぐに参照できるソースはこちら

<!DOCTYPE html>
<html>
<head><title>Wiggle problem</title>
<style>
#dback {
    width: 200px;
    height: 200px;
    background-color: red;
}
#dfront {
    width: 200px;
    height: 200px;
    background-color: blue;
}
</style>

<script type="text/javascript">
var run = false;
function playpause() {
    if ( run ) {
        run = false;
    } else {
        run = true;
        update();
    }
}

function update() {
    if ( run==false ) {
        return;
    }

    var el = document.getElementById('dfront');
    if ( el.style.display != 'none' ) {
        el.style.display = 'none';
    }
    else {
        el.style.display = '';
    }

    setTimeout("update();", 100);
}
</script>

</head>

<body>
<a href="#" onclick="playpause();">play/pause</a>
<div id="container" onclick="d=new Date();t=d.getTime();document.getElementById('info').innerText='click '+t;">
    <div id="dback">
        <div id="dfront"></div>
    </div>
</div>
<span id="info"></span>
</body>
</html>
4

2 に答える 2

1

それは本当に奇妙です!ただし、いくつかのテストを作成し、コードを少しいじりましたが、バブルとは何の関係もないと思います (私のテストでは、visibility: hiddenバブルのある要素をクリックしても問題ありません)。

タイマー間隔が非常に短いため、実際のクリックを登録するのに十分な時間がありません。クリックはイベントであり、その後に同じ要素でイベントmousedownが続きます。mouseupあなたの場合mouseup、それは他の要素で頻繁に発生しており、同じものでmousedownはなく、clickイベントが発生していません。上記の 2 番目のリンクを参照してください。間隔を 1 秒に短縮し、青い四角をクリックして、赤い四角でマウス ボタンを離します (またはその逆)。何も起こりません。私は完全に間違っているかもしれませんが、それはもっともらしく見えます。

これが解決策ではないことはわかっていますが、あなたは次のように述べています。

ですから、解決策が得られなくても、何が問題なのかを理解したいと思います。

これがあなたを見つけるのに役立つことを願っています!

最後になりましたが、コードに関するいくつかの補足事項:

  1. 呼び出す方法setTimeout(文字列を渡す) は、eval内部での使用を強制するため、推奨されません。可能な限りeval回避する必要があります。関数呼び出しコードで文字列を渡す代わりに、関数自体を渡すだけです。

    setTimeout(update, 100);
    
  2. . _ addEventListener_ attachEvent _ onclick="..."これには、動作、構造、およびレイアウトを分離するのに役立ち、イベント オブジェクトをイベント ハンドラーで (ハンドラー関数の最初のパラメーターとして) 自動的に使用できるようにするなど、いくつかの利点があります。

于 2012-05-06T01:53:31.710 に答える
0

実際には、「dfront」が表示されているときに「コンテナ」にカーソルを合わせ、クリックするとイベントが「dfront」に移動します。ただし、「dfront」要素には onclick イベントはありません。「コンテナ」の Onclick イベントは子要素に伝播しません。これは通常、イベントの「イベント伝播」オプションを持つ jquery を使用して回避できます。または、「dfront」の onclick イベントを設定するだけです。

また、「コンテナ」と「dfront」の上に透明なレイヤーを作成し、イベントをバインドすることもできます。または、window オブジェクトで onmouseclick イベントを作成します。これは、マウスの位置が "dfront" を超えているかどうかを座標で確認し、true の場合はイベント ハンドラーが起動されます。

于 2012-05-05T21:21:23.693 に答える