2

次のHTMLがある場合:

<html>
   <div id="main_content">
      <button>click me</button>
      <script src="main.js" ></script>
   </div>
</html>

そしてmain.js:

$('#main_content').on('click', 'button', function() {
    console.log('you clicked');
});

ページ全体を読み込む場合、ボタンをクリックすると、コンソールメッセージが1つだけ登録されます。ただし、その後AJAXリクエストを介してコンテンツを再ロードmain_content'sすると、ボタンをクリックするたびに2つのコンソールメッセージが表示されます。後続のAJAXロードごとに3,4,5...メッセージが表示されますが、ページ全体をリロードする場合は常に1つです。

誰かがこの振る舞いを説明し、可能な解決策を提案するかもしれませんか?

4

4 に答える 4

5

これは、main.jsの複数のコピーをロードしているため、毎回もう1つのイベントハンドラーをアタッチしているためです。
ロードするたびに、<script>もう1つのハンドラーがアタッチされます

 <button>click me</button>
  <script src="main.js" ></script>

ここでの教訓は、ajaxによってロードされたスクリプトが解析されるため、ハンドラーが含まれている場合はそれらがアタッチされるということです。

于 2012-06-20T21:48:45.070 に答える
3

そのスクリプトを常にリロードする必要がある場合は、次のようにします。

$('#main_content').off("click").on('click', 'button', function() {
    console.log('you clicked');
});

それ以外の場合は、明らかに別の場所に配置します。

于 2012-06-20T21:50:16.180 に答える
1

#main_contentイベントハンドラーはリロードされるたびに切り離されるため、そのスクリプトを、すべてのスクリプトが通常存在するヘッドセクション内ではなく、リロードされたコンテンツに配置したと思いますか?さて、別の方法があります:

$(function(){
   ...
   $('body').on('click', '#main_content', function() { console.log('You clicked!'); });
});

このコードは一度だけ配置、ロード、実行でき、問題のブロックがリロードされるたびにイベントを再アタッチする必要はありません。

ただし、body私のコードでは、より具体的な要素に置き換える方がよいことに注意してください。完璧な世界では、#main_content要素の直接の親です。

更新:これはいわゆるイベント委任と呼ばれ、 .ondocpageで非常によく説明されています。以前のバージョンのjQueryでは、.liveまたは.delegateメソッドのいずれかを使用する必要がありました。

于 2012-06-20T21:55:23.880 に答える
1

すでに述べたように、main.jsは、を実行するたびに再解析および再実行されます.load()

これを解決するには、いくつかのオプションがあります。

  1. main.jsを動的にロードされたコンテンツの外に移動して、を実行するたびに再解析および実行されないようにします.load()
  2. main.jsを変更して、スクリプト全体が1回だけ実行されるようにします。
  3. main.jsを変更して、複数回読み込まれることを認識し、同じイベントハンドラーを繰り返しインストールしないようにします。

これらは、実装が簡単な順に示されています。

オプション2の場合、main.jsのすべてを次のifようなステートメントに入れて、一度だけ実行されるようにすることができます。

if (!window.__main__js__defined) {
    window.__main__js__defined = true;

   // rest of main.js code here

}

オプション3の場合、重複防止保護が必要な個々のイベントハンドラーを保護する必要があります。おそらく.data()、各オブジェクトを使用して、特定のイベントハンドラーを既にインストールしているフラグを設定します。

于 2012-06-20T22:05:30.250 に答える