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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

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

Q&A

解決済

3回答

1509閲覧

二つのHTMLを比較し、『異なる部分を置換』する方法

musume8

総合スコア30

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

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

0グッド

0クリップ

投稿2020/12/25 12:56

編集2020/12/26 06:41

前提・実現したいこと

jQueryの質問になります。

二つのHTMLを比較し、『異なる部分を置換』する方法を知りたいです。

該当のソースコード

次のソースコードは、iniObjからHTMLを生成し、ボタンクリックでnewObjのHTMLへと『すべてを置換』しますが、これを『異なる部分を置換』という風にしたいのです。

『異なる部分を置換』というのは『iniObjとnewObjの値を比較して、HTMLの異なる部分を置換』という意味で、たとえば『user_idが異なればHTMLのその部分だけを置換し、titleが異なれば以下同文』です。

html

1<button type="button">ボタン</button> 2<div class="box"> 3 <!-- 4 読み込み時 5 → iniObjから生成されたHTMLが入ります 6 ボタンクリック時 7 → iniObjとnewObjの値を比較して、HTMLの異なる部分を置換します 8 --> 9</div>

jQuery

1// 読み込み時 2const iniObj = {user_id:1,user_name:'鈴木',title:'今日の天気'}; 3const html = getHtml(iniObj); 4$('.box').html(html); 5 6// HTML生成 7function getHtml(obj){ 8 const 9 user_id = obj.user_id, 10 user_name = obj.user_name, 11 title = obj.title; 12 return ` 13 <div> 14 <p class="userdata user_id">${user_id}</p> 15 <p class="user_name">${user_name}</p> 16 <p class="post_title">${title}</p> 17 </div>`; 18} 19 20// ボタンクリック時 21$('button').click(function(){ 22 const newObj = {user_id:2,user_name:'山田',title:'今日の天気'}; 23 const html = getHtml(newObj); 24 $('.box').html(html); 25});

試したこと

次の流れで考えています。

躓いているのは「一致しない文字列のクラスを取得」の部分です。

あと'userdata user_id'のように複数クラスがある場合の置換もできません。(findメソッドが単一クラスにしか対応していないため?)

jQuery

1// ボタンクリック時 2$('button').click(function(){ 3 // 2つのHTMLを取得する 4 const iniHtml = getHtml(iniObj); 5 const newObj = {user_id:2,user_name:'山田',title:'今日の天気'}; 6 const newHtml = getHtml(newObj); 7 8 // 一致しない文字列のクラスを取得 9 let classNames = ['userdata user_id','user_name']; 10 11 // そのクラスだけを置換する 12 classNames.forEach(function(className){ 13 const html = $(newHtml).find('.'+className); 14 $('.box').find('.'+className).html(html); 15 }); 16});

補足情報(FW/ツールのバージョンなど)

あくまで『異なる部分を置換』であって、『すべてを置換』ではないというのが難しいところです。
jQueryは3.4.1です。
良いお考えがございましたらご回答宜しくお願い致します。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2020/12/25 14:17

> 異なる要素だけを置換 したら、すべての要素が同一、と言うことになるわけですが、 単純にコピーしてしまうのとどういう違いがあるんでしょうか
musume8

2020/12/25 14:28

> したら、すべての要素が同一、と言うことになるわけですが、 おしゃる通りです。 > 単純にコピーしてしまうのとどういう違いがあるんでしょうか 「単純にコピーしてしまう」というのは、「ただ置換するだけ(該当のソースコードの方法)」という意味ですよね? で「ただ置換するだけ」ですと、画像を置換したときに読み込みが発生しますし、まぁ諸事情ということでそこは突っ込まないでくださいまし。
A_kirisaki

2020/12/25 14:29

> 異なる要素だけを置換 それをやってるのが React やで
musume8

2020/12/25 14:47 編集

なるほど、Reactという言葉はなんとなく聞いたことがある程度でまだ使いこなせなそうです。
Lhankor_Mhy

2020/12/26 02:40

『異なる要素だけを置換する』とのことですが、一方で『user_idが異なればそれだけを置換し、titleが異なればそれだけを置換』とも書かれています。ここで言うuser_idなどは変数のことかと思いますが、これは要素ではないと思います。 ご想定されていることは本当に『異なる要素だけを置換する』なのか、今一度整理していただけませんか?
musume8

2020/12/26 04:53

たしかに、『user_idが異なればその要素だけを置換し、…』と書くべきでしたね。わかりにくい文章で申し訳ございません。
Lhankor_Mhy

2020/12/26 04:58 編集

いえ、そういう指摘ではありません。 「user_idが異なれば」とありますが、user_idに要素が入っているわけではないので、要素を比較しているわけではないと思います。「異なる要素」と言いながら実際には文字列を比較している、という指摘です。 つまり、一言で言うと「異なる要素」の定義をご提示ください、ということです。何が同じなら同じ要素とみなして、何が違うなら異なる要素とみなすのか、お示しください。
musume8

2020/12/26 06:42 編集

なるほど失礼致しました。「異なる要素」という表現が誤解を招いていたのだと思います。「異なる部分」とし、質問文を編集致しましたのでご査収いただけましたら幸いです。
Lhankor_Mhy

2020/12/26 12:41

すみません、言葉ではなくて仕様の話なのですが…… あまりしつこくするのも失礼だと思いますので、ご提示のコードから読み解くようにします。 ありがとございました。
guest

回答3

0

ベストアンサー

ご提示のコードを拝見する限り、『異なる部分を置換』とはclass属性が一致する要素を差し替える、ということかと思いました。

以下のようにしてはいかがでしょうか?

js

1 classNames.forEach(function(className){ 2 const html = $(newHtml).find('[class="'+className+'"]'); 3 $('.box').find('[class="'+className+'"]').html(html); 4 });

コメントを受けて追記

一致しない文字列のクラスを取得

これでいかがでしょうか。

js

1Array.from($('p', iniHtml)).flatMap(e => 2 $(`[class="${e.getAttribute('class')}"]`, newHtml)[0].textContent !== e.textContent 3 ? e.getAttribute('class') 4 : [] 5);

投稿2020/12/26 13:05

編集2020/12/28 10:49
Lhankor_Mhy

総合スコア36960

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

musume8

2020/12/27 15:47

ありがとうございます。データ属性と同じノリでクラスもそのように指定できたとは知りませんでした。 あとは「一致しない文字列のクラスを取得」ですが、そこは何かイメージございますか?
Lhankor_Mhy

2020/12/28 01:31

ご提示のコードからは、「一致しない文字列のクラスを取得」の仕様が読み取れませんでした。 たとえば、 <p class="userdata user_id">今日の天気</p> <p class="user_name">今日の天気</p> <p class="post_title">今日の天気</p> で、 {user_id:2,user_name:'山田',title:'今日の天気'} だった場合、差し替えない要素はどれですか?
musume8

2020/12/28 08:30

申し訳ございません。そちらのたとえはつまり const iniObj = {user_id:'今日の天気',user_name:'今日の天気',title:'今日の天気'}; によって <p class="userdata user_id">今日の天気</p> <p class="user_name">今日の天気</p> <p class="post_title">今日の天気</p> が生成されていて const newObj = {user_id:2,user_name:'山田',title:'今日の天気'} が与えられるという状況ですね。 であればボタンクリックで以下に変更したいです。 <p class="userdata user_id">2</p> <p class="user_name">山田</p> <p class="post_title">今日の天気</p> 異なる部分だけが変わった。というのはこのような機能を考えています。
Lhankor_Mhy

2020/12/28 08:33

<p class="post_title">今日の天気</p> を差し替えないということですね。 これは、どういうルールによるものですか? .post_title と newObj.title が対応している、というのは何を参照すれば分かりますか?
Lhankor_Mhy

2020/12/28 09:09

もしかして、iniHtml と newHtml を比較して、class属性が完全一致する要素の文字列を比較し、その文字列が完全一致する場合は置換しない、ということでしょうか?
musume8

2020/12/28 09:22

仰る通りです!その表現に至らずここまで大変な苦労をさせてしまい申し訳ございません。
musume8

2020/12/28 11:36

追記して頂きまして誠にありがとうございます。時間をかけて精読し、使いこなせるように頑張ります。
guest

0

どうしても「一致しない文字列のクラス」を取得したいようなので以下ではどうでしょう。
かなり無駄な処理が入っていますが、getHtml()関数は入力によって定型的に値を返すだけなので本題はobj側の差異を見つけることでしょう。

// 2つのHTMLを取得する const iniHtml = getHtml(iniObj); const newObj = {user_id:2,user_name:'鈴木',title:'今日の天気',test:"test"}; const newHtml = getHtml(newObj); // 一致しない文字列の配列 let classNames = []; // 一致しない文字列のクラスを取得 Object.keys(newObj).forEach(function(i){ if(iniObj[i]){ if(newObj[i] == iniObj[i]){ classNames.push(i); } }else{ classNames.push(i); } }); // そのクラスだけを置換する classNames.forEach(function(className){ const html = $(newHtml).find('.'+className); $('.box').find('.'+className).html(html); });

投稿2020/12/27 16:24

unrealsho

総合スコア93

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

musume8

2020/12/28 08:27

ありがとうございます。そちらclassNamesにクラス名でなくオブジェクトのキーが入ってしまいます。しかしHTML側にそのキーがクラス名として付与されていないので(そしてgetHtml()関数は変えたくないので)、実現できないです…
guest

0

一致しないセレクタを探すのに要素を回すわけですから、予め一致しないセレクタのオブジェクトを用意するのは無駄ではないでしょうか?

forEachで回すならif文で差異が発見できるかどうかclassName毎に条件分岐すれば実装できると思います。

また、htmlメソッドで上書きするだけでなくvalメソッドやtextメソッドで変更を加える部位を最小限にすることもバグの減る実装方法なので一考してみてください。

投稿2020/12/26 09:38

unrealsho

総合スコア93

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

musume8

2020/12/27 15:48

なるほど。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問