鬼勉強でWEBエンジニアに未経験転職した、かわうそです!
今日のテーマ:『jQuery| 1行でcloneするだけ。外部ファイルは読み込まず、ページ内で共通化パーツを作成する方法』
この記事を読めば、『外部ファイルは読み込まず、ページ内で共通化パーツを作成する方法 』が、たったjQuery1行で可能に!
結論:1行。jQueryのcloneメソッドでコピー、appendToメソッドで動的にDOMを作成するだけ。JavaScriptだけでも簡単に実装可能です。
皆さんなら、ソースを分け、ヘッダーやフッターのように外部ファイルにして読み込めばいいじゃん? と思われるでしょう!
なぜそうしなかったのか、こういう背景がありました。
- パーツ化したいのは、そのページでしか使用しない特殊なコンバージョンボタン
- ソースを切り分けるほどの記述量はないが、頻繁に使用するのでページ内部でパーツ化したい
こんな小さなパーツのために、管理ソースをこれ以上増やしてたまるかー!という気持ちでした。サイト規模が大きい。
心の声:テキストエディターで作業するソースが多いと、めんどい
というわけで、jQueryのcloneメソッドで簡単に実現できたので解説します。
ついでに、脱jQueryの、JavaScriptバージョンも合わせて解説します!
※脱jQuryのためにJavaScriptを学ぶには、こちらの3万部越えの書籍が良書。書籍選びに迷ってる人は、間違いなし。 レベルは理解できれば中級、全くの初級者にはかなり難しい。入浴中まで読みまくりボロボロのかわうそのバイブル 。
Contents
jQueryのcloneメソッドで 共通化パーツを作成
結論、jQueryのこの一行でOK!
1 |
$(共通化パーツ).clone(true).appendTo(共通化パーツを作成したい場所); |
かんたんなサンプルコードを用意しておきます
HTML
1 2 3 4 5 |
<div class="clone"> <span>クローンします</span> </div> <div class="clone_set"></div> |
jQuery(JavaScript)
1 2 3 |
$(function(){ $('.clone').clone(true).appendTo('.clone_set'); }); |
cloneをコピーし、clone_setにコピーを生成します
実装
clone_setの分だけ、コピーが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<div id ="sample1"> <div class="clone"> <span>クローンします</span> </div> <div class="clone_set"></div> <div class="clone_set"></div> </div> <script> $(function(){ $('#sample1 .clone').clone().appendTo('#sample1 .clone_set'); }); </script> |
ページ内で繰り返し使用したいパーツは、クローンして、動的に生成すればok。このぐらいの記述なら、ソースを切り分け、管理ファイルが増えるよりは楽です
JavaScriptがページ内を全捜査するので、多用しすぎることはおすすめしません
cloneメソッドは引数によって少し性質が変わるので、説明しておくよ
cloneメソッド:第一引数
第一引数は論理値です(true,false)
trueならイベントもコピー、falseならイベントはコピーされません。引数に何も入れなければ、falseと同じ挙動をします。
こちらも例題を用意します
clone(true):イベントもコピー
clone(true)の場合は、クローン後のボタンをクリックしても、クローンが生成されます。つまり、クリックイベント設定までコピーされます
1 2 3 4 5 6 7 8 9 10 |
<p class="clone_true">クリックしてクローン</p> <p class="clone_true_set"></p> <script> $(function(){ $('.clone_true').click(function(){ $(this).clone(true).appendTo('.clone_true_set'); }); }); </script> |
クリックしてクローン
clone(false)または clone() :イベントはコピーされない
clone(false)または clone() の場合は、クローン後のボタンをクリックしても、クローンが生成されません。
1 2 3 4 5 6 7 8 9 10 |
<p class="clone_false">クリックしてクローン</p> <p class="clone_false_set"></p> <script> $(function(){ $('.clone_false').click(function(){ $(this).clone(false).appendTo('.clone_false_set'); }); }); </script> |
クリックしてクローン
脱 jQuery:JavaScriptではcloneNodeメソッドで実現可能
JavaScriptではcloneNodeメソッドで実現可能です。
ただし、jQueryのcloneメソッドのように使おうと思うと、すこし調整が必要で癖があります。
そのあたりも詳しく解説しておきますね。
JavaScriptで書けるとかっこいいよね
jQueryは分かるけど、JavaScriptは分からん!って人はこのへんの記事がおすすめです
完成品
以下が完成品
js_clone_setの数だけ、クローンされます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<p class="js_clone">JSでクローン</p> <p class="js_clone_set"></p> <p class="js_clone_set"></p> <script> let targetClone = document.querySelector('.js_clone'); let cloneSet = document.querySelectorAll('.js_clone_set'); let cloneCopy; for(i = 0; i < cloneSet.length; i++){ cloneCopy = targetClone.cloneNode(true); cloneSet[i].appendChild(cloneCopy ); } </script> |
JSでクローン
JavaScript cloneNodeメソッドの解説
1行ずつ順に解説していきます
1行目
let targetClone = document.querySelector('.js_clone');
. js_clone を取得し、クローンする要素を変数に格納しました。
2行目
let cloneSet = document.querySelectorAll('.js_clone_set');
. js_clone_set を取得し、クローンを生成する要素を変数に格納しました。
ポイントは querySelectorAll メソッドの使用です。
.js_clone_setは複数に設置されることが予測されます。
querySelectorメソッドはヒットした最初の要素だけしか返しません。 querySelectorAll メソッド を使ってすべての要素リストを取得しましょう。
console.logでcloneSetを確認すると
1 2 3 4 |
NodeList(2) [p.js_clone_set, p.js_clone_set] 0: p.js_clone_set 1: p.js_clone_set length: 2 |
要素数は2個、NodeList形式[配列] になっていることも分かります。
3行目
空変数:cloneCopy を作成しました
4行目以降
for(i = 0; i < cloneSet.length; i++){
cloneCopy = targetClone.cloneNode(true);
cloneSet[i].appendChild(cloneCopy );
}
ここからがポイントです。for文の詳しい説明については割愛します
for文では、 cloneSet.length の数だけ繰り返し処理が起きるようにします。 cloneSet.length は、2行目で変数に格納した、 .js_clone_set の数を吐き出します。
なんで繰り返し処理が必要になる理由は以下です。
- クローンする数だけ、cloneNodeメソッドで生成する必要がある
- クローン先を格納した変数のcloneSetが、配列形式(ノードのリスト)になっている
これだけだと分からないと思うので、さらに深く解説します!
5行目:for文内、cloneNodeメソッドについて
cloneCopy = targetClone.cloneNode(true);
すこしややこしいですが、 1行目でクローン元の要素を格納した変数 targetCloneをcloneNodeメソッドでコピーし、変数cloneCopyに再格納しています。
確認で、cloneNodeメソッドの結果を、console.log()で調べてみましょう。
1 2 3 4 5 6 7 8 9 10 |
<p class="get_sample">クローンされます</p> <script> let getSample= document.querySelector('.get_sample'); let cloneSample = getSample.cloneNode(true); console.log(getSample); console.log(cloneSample); </script> |
どちらも、<p class="get_sample">クローンされます</p>になり、コピーされていると分かります。
ちなみに、for文内でcloneしているのは、生成分のclone数を確保するためです。ピストルの弾のように、生成するとクローンはなくなりますので、毎回クローンが大切です。(後で説明する、appendChildの仕業です)
6行目
cloneSet[i].appendChild(cloneCopy );
生成先に 、appendChildメソッドを使用し、コピーしたクローンを作ってやりましょう。
↓めっちゃ大事です!!↓
appendChildメソッドを使用すると、 cloneCopy は削除されます。ピストルの弾の消費は、 appendChildメソッドの実行なのです。ぶっちゃけクローンしなくても良いや、と思ったりしましたが、クローンしないとクローン元が無くなってしまうので、エラーが起こります。
ポイントは、 cloneSet[i]です。
生成先は同じクラス名になっており、配列として格納されていることを確認しましたね。
それぞれが異なる位置情報、DOMのツリー構造の中で、どこに位置しているのか情報を持っています。
例えば、コンソール画面で
cloneSet[0].previousElementSibling
と入力してみてください。 最初のcloneSetクラスの、1つ前の要素が何か調べてくれます。当然、以下が返ります。
<p class="js_clone">JSでクローン</p>
今度は
cloneSet[1].previousElementSibling
と2つ目のcloneSetの直前要素を調べてみましょう。
<p class="js_clone_set"></p>
今度も、直前の要素が確認できましたね。
このように、1つ1つの要素は、DOM構造全体の中のどこにあるのか、情報を持っているのです。
だからこそ、 cloneSet[i] を使用し、それぞれに対してappendChildメソッドで、クローン生成を指示してあげることが大切です。
cloneNodeメソッドの引数
cloneNodeメソッドの引数は、jQueryと異なるので注意。
- true:子要素まで全てを複製(深い複製)
- false:子要素は複製しない(浅い複製)
また、全ての属性はコピーされますが、イベントリスナーなどで設定したイベントはコピーされません。
結論:jQueryが楽すぎる
望んだ挙動をするのは、jQueryですね!
jQueryなら1行で終わってしまうので、JavaScriptで書くと時間はかかりそうです。
ただ、JavaScriptの深い理解をし、プログラミング技術力向上のためには、jQueryを使用せずに書いてみるのが良いと思います!
※冒頭でも書いた通り、 JavaScriptを学ぶにはこちらの本が名著です。初心者には少し難しいかも。