ワテの場合、2015年くらいからWEBプログラミングを始めた。
開発環境は、その当時はVisual Studio 2013を使っていたが、現在は無料版のVisual Studio 2017 Communityを使っている。
Visual Studio においては、WEBサイト作成用の開発環境も充実していて、
- ASP.NET サーバーOSはWindows
- ASP.NET MVC サーバーOSはWindows
- ASP.NET Core サーバーOSはWindows, Linux, Mac
と言った開発手法(と言うか開発技術と言うべきか、ワテは良く知らないが)が標準で用意されている。
WEBプログラミングでは、クライアントサイド(ブラウザー側での処理)とサーバーサイドでの処理が必要になる。
上で紹介したASP.NET 関連手法を使うとVisua Studioの統合開発環境IDEの下でC#、VB.NET、PHP、TypeScript、JavaScriptその他多くの言語を使ってサーバーサイドで実行するプログラムを開発出来る。もちろんクライアントサイドの開発も同時に行う事が出来て、Typescript、JavaScriptなど各種の言語を利用出来る。
最近ではWindows, Linux, Macの各OSで稼働するASP.NET Coreもバージョン1.1から2.1に上がったので、ワテも使い方を勉強中だ。
クライアントサイドのプログラミングに於いては、JavaScritpが良く使われる。
さらにjQueryと言う便利なJavaScript向けの無料ライブラリも一緒に使う事が多い。
しかしながらjQueryは便利な反面、jQueryを使った事による弊害も多い。
そう言う事情があって、最近のワテは脱jQueryをして純粋なJavaScriptのみでプログラミングするように心掛けている。
当記事は、その備忘録。
簡単なクライアントサイドプログラムなら、ここで紹介している程度の手法を覚えておけば、jQueryを排除してJavaScriptのみでプログラミング可能だ。
では、本題に入ろう。
jQueryは便利だけれど使わなくてもプログラムは書ける
ワテがJavaScriptを使ってWEBプログラミングを始めた当初は、WEBプログラミングとはどんなものかさえ知らなかったのでネット検索しまくった。
WEBプログラミングとは何か?
WEBプログラミングとは何か?を定義するのは難しい。広範囲に渡るからだ。
でも、クライアントサイドのWEBプログラミングに限定すれば、ワテが思い付くのは以下の項目がある。
- マウスクリックなどのイベントの処理
- HTMLの内容を動的に変更する
などかな。勿論これら以外にも有るとは思うが、ワテがクライアントサイドWEBプログラミングで思い付くのはこれくらい。
マウスクリックなどのイベントの処理の例
例えばショッピングサイトで商品の横にボタンが有って、それをクリックするとショッピングカートにその商品を追加する。
こんな感じか。
なお、ワレコのサイトでは物品は販売していない。
もし上のスイーツを本当に購入したい人は画像クリックして開くアマゾンで買って下さい。
ボタンクリックイベント処理をするJavaScriptコードの例を以下に示す。
<button id="my_button1_ID">ショッピングカートに追加する</button> <script> $('my_button1_ID').on('click', function(){ alert('カートに追加しました。'); }); </script>
上のコードを初めて見る人は、大体は理解出来るとは思うが、ドル記号 $ って何?と思っているに違い無い。
jQueryの登場
さて、WEB初心者だった当時のワテは、上の数行のJavaScriptコードを見ても何となく分るが、不明な点も多かった。
$って何よ?
$( )って何よ?
と言う感じだ。
まあ、今となっては理解出来ているので混乱する事は無いが、正解を言うと $がjQueryを表す訳だ。
jQueryとは
で配布されているJavaScriptで書かれた便利なライブラリ。
そのjQueryを使う場合には、jQueryと言う名前自体が関数でもあり、以下のような書き方が出来る。
var divJQ = jQuery('div'); // divタグを全部取得してjQueryオブジェクトの配列にする divJQ.on('click', function(){・・・} ); // divクリック時のイベントハンドラ設定 jQuery('div').on('click', function(){・・・} ); // divクリック時のイベントハンドラ設定(上と同じ)。'タグ名'形式セレクター jQuery('#my_button1_ID').hide().show(); //メソッドを連結しても良い。'#ID'形式のセレクター $('#my_button1_ID').hide().show(); //メソッドを連結しても良い。jQueryは$に置き換えても良い
上で紹介したjQueryの記述方法は、ほんの一部なのでこれ以外にもいろんな書き方が出来る。
$記号はjQueryに置き換えても良い。
つまり$()は関数であり、jQueryライブラリを呼び出す事が出来るのだ。
jQueryを使うとDOM操作が簡単
DOMとはDocument Object Modelであり、まあ専門的な解説は各自調査して頂くとして、ワテの理解ではDOMとは、ブラウザーが表示しているhtmlの事だ。
このワテのページを見ている皆さんは、もしパソコン画面で見ているならブラウザーのF12キーを押してみると良い。
さて、単純なhtmlの例を示そう。
<div> <h1>タイトル</h1> <div> <h2>第一章</h2> <p>文章を書く・・・・・・・</p> </div> <div> <h2>第二章</h2> <p>文章を書く・・・・・・・</p> </div> <div> <h2>結論</h2> <p>文章を書く・・・・・・・</p> </div> </div>
例えばこのhtmlに於いて、三か所にあるh2タグの背景色を変更したい。
<script> $('h2').css('background-color', 'red'); </script>
こんな感じか。
あるいは、こんな風に書くとh1もh2も変更出来る。
<script> $('h1, h2').css('background-color', 'red'); </script>
こんな感じか。
あるいは divタグの中のpタグの背景色を変更したい。
<script> $('div p').css('background-color', 'red'); // divの中のp全部(子要素、孫要素など全て) $('div > p').css('background-color', 'red'); // divの中の子供p全部(子要素のみ、孫要素は対象外) </script>
こんな感じか。
まあ、要するにjQueryと言うのは、セレクターで操作対象となるhtml要素を選択しておいて、それらに対してメソッドを実行出来るのだ。
jQuery('セレクター文字列').method1().method2().method3();
この場合、以下のように書き換えても良い。
var elemJQ = jQuery('セレクター文字列'); // elemJQはjQueryオブジェクトの配列 elemJQ.method1().method2().method3();
つまりまあ、elemJQは配列になる訳だが、forループなどを書かなくてもjQueryライブラリ側で自動的にループ処理をして、jQueryオブジェクト配列の各jQueryオブジェクト要素に対して後ろに連結されているメソッドを順次実行してくれるのだ。
ああ、便利!
確かに、WEBプログラミングを覚え始めた当初は、jQueryって何て便利なんだろうと感心した。
そしてそれを使って約三年になる。
jQueryとの決別宣言
しかしまあ、人間、楽していると体が鈍るのと同じで、jQueryを使いまくっていると弊害も多いのだ。
具体的に言うなら、ワテが直面したjQueryの弊害は以下の通り。
- 取り敢えずDOM操作で何かする場合には、jQueryに頼ってしまいJavaScriptの勉強にならない
- JavaScriptコードの中に矢鱈と$記号が目立つのだが、PHP変数も $hensu 形式で$が付くので紛らわしい
- jQueryライブラリのロードが完了しないと、jQueryを使うプログラムが動かない
- 特にWordPressサイトの場合にjQuery多用するとサイト表示速度が低下する
などか。
と言う訳で、最近のワテは脱jQuery宣言をしたのだ。
ちなみにこれは、非実力派宣言
古いわ。もう完全にオバサンやがな。
さて、本題に戻ろう。
jQueryで出来る事はJavaScriptでも出来る
そもそもjQueryはJavaScript言語で記述されている訳だから、jQueryで出来る事はJavaScriptでも出来るのだ。
クラス操作をJavaScriptで書く
まずはクラス操作をJavaScriptでやる事にする。
jQuery AはjQueryオブジェクト配列 |
JavaScirpt AはNode Element |
A.addClass('B') |
A.classList.add('B') |
A.hasClass('B') |
A.classList.contains('B') |
A.removeClass('B') |
A.classList.remove('B') |
A.toggleClass('B') |
A.classList.toggle('B') |
なお、jQueryの場合なら複数の要素に対して一行で書ける。
$('div').addClass('B');
上の例では、もしDOMの中に<div>タグが複数ある場合には、$(‘div’)はjQueryオブジェクトの配列となる。
その配列に対して、自動的にaddClass()が実行されるのだ。
一方、JavaScriptの場合には、配列に対して自分でループ処理をすれば良い。
let divJS = document.querySelectorAll('div'); divJS.forEach(function (div_i, i) { // forEachはIE11未対応 div_i.classList.add('B')) { }); //IE11対応のforループ版ならこちら for (var div_i of divJS) { div_i.classList.add('B')) { }
注意事項としては、
querySelector querySelectorAll
の二種類があるが、後者を使う場合はセレクターにマッチする全部のNode Elementを配列で取得するのでforループ処理が必要だ。
jQueryのCSS()関数をJavaScriptで書いてみる
jQueryならstyle設定はcss()関数を使えば以下のように書ける。
$('div').css({ 'float': 'right', 'z-index': '1' });
つまり、cssの引数にJSONオブジェクト
{ 'key' : value [, 'key' : value ...] }
を渡せば良いのだ。
JavaScriptの場合ならこんな感じ。
let divJS = document.querySelectorAll('div'); let i = 0; for( i=0; i < divJS.length; i++ ) { divJS[i].style['float'] = 'right'; divJS[i].style['z-index'] = '1'; }
ただし、これだと設定したいstyle属性が固定なので使い勝手は良く無い。
そこで、ワテが作成したのがJavaScriptでcssのスタイル設定を行う汎用関数だ。
function MyCSS(thisNode, styleObj) { /* 使い方 MyCSS(Node要素, {'float':'right','z-index':'2'} ); */ Object.keys(styleObj).forEach(function (key) { thisNode.style[key] = styleObj[key]; //console.log(key + "は" + styleObj[key] + "です。"); }); }
使い方としては、こんな感じか。
let divJS = document.querySelectorAll('div'); let i = 0; let styleObj = {'float':'right','z-index':'2'}; for( i=0; i < divJS.length; i++ ) { MyCSS(divJS[i], styleObj); }
forループで個々のNode Elementに対してMyCSS()をコールしている。
そのforループ部分も関数に入れてquerySelectorAll()で取得したNodeリスト全てに対してstyleをセットする関数を即席で作ってみた。
let divJS = document.querySelectorAll('div'); let styleObj = {'float':'right','z-index':'2'}; MyCSS_ALL(divJS, styleObj); function MyCSS_ALL(nodeList, styleObj){ let i = 0; for( i=0; i < nodeList.length; i++ ) { MyCSS(nodeList[i], styleObj); } }
なお、MyCSS()はテストして動作確認済だが、こちらのMyCSS_ALL関数は今この記事を作成しながら即席で作ったので動作確認はしていない。
各自テストお願いします。
jQueryのinsertBefore()をJavaScriptで作る
まずはjQueryのinsertBefore()関数をJavaScriptで書いてみた。
指定したNodeの一つ前に新規に要素を追加する機能だ。
function MyInsertBefore(thisNode, newNodeStr, classStr) { // thisNode: このノードの前に追加する。Node Element // newNodeStr: 新規追加したいノード名文字列。'div'など // className: 追加する時に与えたいクラスが有れば指定する。文字列。 var newNode = document.createElement(newNodeStr); if (classStr) { newNode.className = classStr; } thisNode.parentNode.insertBefore(newNode, thisNode); return newNode; }
MyInsertBefore()の使い方としてはこんな感じか。
let divA = document.querySelector('div.A'); // querySelectorAllではない var buttonB_added = MyInsertBefore(divA, 'button', 'B');
その結果、DOMは以下のようになる。
<button class="B"></button> これが追加された <div class="A"> ・・・ </div>
多分上手く動くと思うが、各自テストお願いします。
必要ならば関数の引数をもう一個追加して(nodeInnerHtmlなど)、 Nodeを作成すると同時にinnerHtmlをセット出来るようにしておくと便利かも。そうすると、この例ならbuttonに表示する文字列を与える事が出来る。
jQueryのappendTo()をJavaScriptで作る
次は、jQueryのappendTo()モドキをJavaScriptで作ってみた。
function MyAppendTo(thisNode, newNodeStr, nodeInnerHtml, classStr) { /* jQueryのappendToなら var $button1_added = $("<button>ボタン1</button>").appendTo($div); それをJavaScriptで実装した。 thisNode : このノードの前に追加する。Node Element newNodeStr : 新規追加したいノード名文字列。'button'など nodeInnerHtml : 追加する時に与えたいhtmlが有れば指定する。文字列。不要ならnull classStr : 追加する時に与えたいクラスが有れば指定する。文字列。不要ならnull 使い方 var button1_added = MyAppendTo(div_elem, 'button', 'ボタン1', null); */ var newNode = document.createElement(newNodeStr); if (classStr) { newNode.className = classStr; } if (nodeInnerHtml) { newNode.innerHTML = nodeInnerHtml; } thisNode.appendChild(newNode); return newNode; }
MyAppendTo()の使い方としてはこんな感じか。
let divA = document.querySelector('div.classA'); // querySelectorAllではない var button1_added = MyAppendTo(divA, 'button', 'ボタン1', 'B');
その結果、DOMは以下のよになる。
<div class="A"> <button class="B">ボタン1</button> divのchild先頭にこれが追加された 他の要素 </div>
多分上手く動くと思うが、各自テストお願いします。
jQueryオブジェクトとJavaScriptで扱えるDOM要素との相互変換
例えば、jQueryを使ってdiv要素を全部取得したとする。
var divJQ = $('div');
この場合、divJQはjQueryオブジェクトの配列になっている。
このままではJavaScriptでは扱えない。
そこでこのdivJQをJavaScriptでも扱える普通のDOM要素に変換してみよう。変換と言うよりはjQueryオブジェクトは多数のメンバーを持っているのでその中にDOM要素の情報も入っているのだ。
jQueryオブジェクト => DOM要素 へ変換
var divJS_0 = divJQ[0]; // divJQの先頭要素からJavaScriptで扱えるDOM要素を取り出した var divJS_0 = $('div')[0]; // あるいはこれでも良い。 // 全div要素に対して何らかの処理をしたい場合はループすれば良い。 for (var i = 0; 1 < divJQ.length; i++) { var divJS_i = divJQ[i]; alert('nodeName=' + divJS_i.nodeName); // nodeName=div と出るはず。 }
上のように divJQ[i] とすればjQueryオブジェクトをDOM要素に変換出来るのだ。
別の方法もある。
$('div').get(0);
.get()関数を使って上のようにしても良い。
もし.get()関数を引数無しで使うと、jQueryオブジェクト配列をDOM要素配列に変換する事も可能だ。
var divJS = $('div').get(); var divJS = document.querySelector('div'); var divJS = document.getElementsByTagName('div');
上のdivJSはどれもdivタグを全部取得出来る。
DOM要素 => jQueryオブジェクト へ変換
多少、間違っているかもしれないが、ワテの理解では、以下のようにDOM要素を $() で囲めばjQueryオブジェクトに変換出来る。
var divJQ = $(DOM要素); // 兎に角 $() で囲めばjQuery化出来る。はず。
具体例は以下の通り。
var element = document.getElementById('id'); // JavaScriptで扱えるDOM要素を取り出す。 var elemJQ = $(element); // これでjQueryオブジェクトに出来る。 var elemJQ = $('#id'); // この例なら、このほうが手っ取り早いが。
まあ、こんな感じでjQueryオブジェクトとDOM要素は相互に変換出来るので、ワテの場合は、その時の気分でjQueryオブジェクトでDOM操作したり、あるいは、JavaScriptのみでDOM操作したりと、一貫性が無い。
なので、今後はjQueryは排除してJavaScript一本で行く予定だ。
querySelector と getElementsByTagName の違い
さて、JavaScriptでDOM操作する場合に良く使うのがこれらの関数だ。
querySelector()は引数にセレクター文字列を指定すれば、細かく条件を設定出来る。
でも’div’タグを指定すれば同じ結果が得られる。
querySelector('div'); // これと getElementsByTagName('div'); // これは全く同じ?
ワテの場合、今日までこの二つは同じ結果になると思っていた。
でも少し違うらしい。
例えばhtmlにaタグが二つある状態で以下のJavaScriptコードを実行する。
<script> var elem1 = document.getElementsByTagName('a'); // 2要素の配列になる。 var elem2 = document.querySelectorAll('a'); // 2要素の配列になる。 console.log(elem1.length); // = 2 console.log(elem2.length); // = 2 document.body.appendChild(document.createElement('a'));// ここで aタグを動的に一個追加する console.log(elem1.length); // = 3 (↑に連動して一つ増えるのだ!) console.log(elem2.length); // = 2 (こちらは変化なし) </script>
その結果、getElementsByTagNameとquerySelectorAllの実行結果が異なるのだ。
つまりまあ、getElementsByTagNameで取得したelem1の中身は、その後のDOM操作に連動して動的に変化する(らしい)。ワテもその辺りの仕組みを使いこなした事が無いので、実際に試した訳では無い。
一方、querySelectorAll で取得したelem2は取得した時点の物であり、その後のDOM操作には影響されないのだ。
getElementsByTagName : 動的なNodeList (live list) querySelectorAll : 静的なNodeList (static list)
などと呼ばれるらしい。
知らなんだ。
まとめ
当記事ではjQueryで良く行う操作をJavaScriptで記述してみた。
具体的には、以下のjQuery処理をJavaScriptで書いてみた。
- クラスの操作
- css()でstyle属性を設定する操作
- insertBefore()
- appendTo()
まあ、自分で書いてみるとJavaScriptの勉強にもなった。
次の記事では、jQueryのイベント処理をJavaScript化する手法に付いて解説したい。
本を読む
有名な山田さんの本だ。
ふりがなプログラミングって何やねん?
コメント