質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.50%

  • jQuery

    8155questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Node.js

    2360questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • Ajax

    1327questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • Express

    301questions

    ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。

Ajaxでのページ遷移で別の不具合

受付中

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 233

ndata

score 1

前提・実現したいこと

jQuery+Express+Node.jsの勉強をしています。
2つのページをAjaxで更新せずに表示切替させたいと思い調べながら見様見真似で以下のコードを用意しました。
EJS1を初期表示させ、確認ダイアログを押すとEJS2が表示されます。
そのままEJS2で何かキーを押すと再びEJS1が表示されます。

ここまでは良いのですが、EJS1に戻ってきた際にEJS2でキー判定に使ったコードが有効になっているままで、
何かキーを押すとEJS1が表示し直されてしまいます。

また、その状態でEJS2を再び表示するとletで宣言した変数countが
既に宣言されている(HTMLが2回読まれている(?))というエラーが出ます。

Ajaxで一度読み込んだコードはページを離れても捨てることはできないのでしょうか?
あるいは、他に解決策があるのでしょうか。

今日、丸一日調べたり試行錯誤しても全く解決の糸口が見つかりませんでした。
助言いただけると幸いです。

該当のソースコード

       let result = confirm('本当に移動しますか?');
        if (result) {
            $.ajax({
                type:"GET",
                url:"Page1",
                dataType:"html",
                success: function(data){
                    $('body').html(data)
                }
            })
        }    
  let count = 0;
  $(document).keydown(() =>{
    count++
      $.ajax({
        type:"GET",
        url:"helo",
        dataType:"html",
        success:function(data){
          $('body').html(data);
        }
      })
  })
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

誰も回答がないので、敢えて回答しておきます。

ここまでは良いのですが、EJS1に戻ってきた際にEJS2でキー判定に使ったコードが有効になっているままで、
何かキーを押すとEJS1が表示し直されてしまいます。 

これは$(document).keydown()だからだと思います。このイベントはbodyではなく、その上位のdocumentに対してなので、bodyの書き換えでは消えません。なので、EJS1に戻ってもイベントハンドラが有効なままなのです。

また、その状態でEJS2を再び表示するとletで宣言した変数countが
既に宣言されている(HTMLが2回読まれている(?))というエラーが出ます。 

一度目の表示で、(恐らく)letでグローバル定義されたcountがあるので、これが残ります。次にまた(恐らく)グローバル定義されたものが読まれても、これは重複してしてしまうのでエラーです。

以上から、

  • documentに対するkeydownイベントのハンドラ解除
  • グローバル変数でないcountの定義

をしたものを書いてみました。Ajaxのままでは実行も出来ないので、setTimeoutにして流し込むHTMLをグローバルの文字列にしています。ハイライトが不自然になってますが、やってることがやってることなので仕方ないと諦めてください。

<html>
<head>
<script src="jquery-3.3.1.min.js"></script>
<script>
    data1 = "\
<div><h1>ESJ1</h1></div>\
<script>\
(function(){\
    let result = confirm('本当に移動しますか?');\
    if (result) {\
        setTimeout(function(){\
            $('body').html(data2);\
        }, 1);\
    }\
})();\
</" + "script>\
    ";
    data2 = "\
<div><h1>ESJ2</h1></div>\
<script>\
(function(){\
    let count = 0;\
    $(document).on('keydown', () =>{\
        $(document).off('keydown');\
        count++;\
        setTimeout(function(){\
            $('body').html(data1);\
        }, 1);\
    });\
})();\
</" + "script>\
    ";
</script>
</head>
<body>
<script>
$('body').html(data1);
</script>
</body>
</html>

正直なところ、言いたいことはいろいろありますが、どうしてこんなコードになっているのか、理由も分からないので、1つだけ絶対言っていた方がいいことだけ言っておきます。
スクリプトを流し込むのは止めた方がいいです
よく分からないうちは危ないので。


■追記-1
ご指摘があったので、きちんと書いておきます。

今回サンプルで書いたものは、埋め込んだグローバル変数の内容を使っていますが、これはサンプルコードをサーバーなしで動かせるように、本来Ajaxから受け取るはずのデータを書いたものです。なので、この質問者さんの環境でサンプルコードをそのまま使用することはできません。回答そのものは自分で考えて欲しいということもあり、実際の修正内容を載せていなかったのですが、ご指摘で懸念されているように、よく分からずこのまま使用するというのはさらに良くないので、私のサンプルを実際に適用した回答を併記することにしました。

// EJS1
(function(){
    let result = confirm('本当に移動しますか?');
    if (result) {
        $.ajax({
            type:"GET",
            url:"Page1",
            dataType:"html",
            success: function(data){
                $('body').html(data);
            }
        });
    }
})();    
// EJS2
(function(){
    let count = 0;
    $(document).on('keydown', () =>{
        $(document).off('keydown');
        count++;
        $.ajax({
            type:"GET",
            url:"helo",
            dataType:"html",
            success:function(data){
            $('body').html(data);
        }
    });
})();


なお、このコードは、動くようにした(つもり)のものというだけなので、スクリプトの流し込みはそのままの想定になっており、良くないです。ご自分で考えて頂いて、<script>〜</script>要素をAjaxで流し込むのは止めましょう。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/02 19:42

    埋め込みは怖いですね
    出来れば、後から読む人の為に「ajaxを使え」って目立つように書いていただけないでしょうか?

    キャンセル

同じタグがついた質問を見る

  • jQuery

    8155questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

  • Node.js

    2360questions

    Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

  • Ajax

    1327questions

    Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

  • Express

    301questions

    ExpressはNode.jsのWebアプリケーションフレームワークです。 マルチページを構築するための機能セットおよびハイブリッドのWebアプリケーションを提供します。