クライアントサイドJavaScript

はじめに

素のJSを学んでいこう月間ということで今日はクライアントサイドJavaScriptについて学んでいきます。

✅ゴール
・JS理解を深める

✅参考教材
📚改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで ES6基準の書籍
※以降、本格入門

📚パーフェクトJavaScript
※以降、PFJS

クライアントサイドJavaScript

✅DOM(Document Object Model)

DOMは、マークアップ言語で書かれたドキュメントにアクセスするための標準の仕組み。API。

ドキュメントを文書ツリーとして扱い、文書に含まれる要素や属性、テキストをそれぞれオブジェクトとみなして「オブジェクトの集合(階層関係)が文書である」と考える。

特に、文書を構成する要素や属性、テキストといったオブジェクトのことをノードと呼ぶ(要素ノード、属性ノード、テキストノードなど)。

✅要素ノードの取得(documentオブジェクト)

HTMLやCSSを操作するための機能が多数用意されている。

①getElementByIdメソッド

id値をキーに要素を取得する。

textContentプロパティは取得した要素に対してテキストを埋め込む

document.getElementById('ID名').textContent = 書き換えたい文字列;

例)

<p id="choice">ここに日時を表示します</p>
<script>
  'use strict';
  document.getElementById('choice').textContent = new Date();
</script>

②getElementsByTagNameメソッド

タグ名をキーに要素を取得する。getElementByIdと違い複数形で戻り値は要素の集合になる。

index.js

var current = new Date();
var result = document.getElementById("result"); // id属性
result.textContent = current.toLocaleString();
console.log(result.textContent);

var list = document.getElementsByTagName("a");
console.log(list.item(0).href);
// console.log(list[0].href); // 別パターン

※console.log(list.href)だとundefinedとなる。

index.html

<h1>test</h1>
現在時刻:<span id="result"></span>
<a href="https://chobimusic.com">blog</a>
<script src="./index.js"></script>

③querySelector/querySelectorAllメソッド

上記のgetXxxメソッドが特定の名前/属性値をキーに要素を検索していたのに対して、複雑な条件での検索を可能にする。

index.js

var select = document.querySelector("h1");
console.log(select);
var select = document.querySelectorAll(".h2-class");
console.log(select);

index.html

<h1>test</h1>
<h2 class="h2-class">test-h2</h2>
<h2>test-h2-2</h2>
<script src="./index.js"></script>

📝getXxxメソッドの方がqueryXxxメソッドより高速。基本はgetで複雑な検索をしたい場合にqueryを用いる。

✅イベント

イベントドリブンモデル(イベント駆動型モデル):イベントに応じて実行するコードを記述するプログラミングモデル。クライアントサイドJavaScriptの特徴。

イベントに対応してその処理内容を定義するコードのかたまり(関数)のことを、イベントハンドラー(イベントリスナー)と呼ぶ。

イベントハンドラーの設定

<タグ名 onイベント名="JavaScriptのコード">

index.htmlとindex.js

<!-- ①.htmlにJSの記述をする -->
<input type="button" value="ダイアログ表示" onClick="btn_click()" />

<!-- ②.htmlにJSの記述をしない -->
<input id="btn" type="button" value="ダイアログ表示"/>

<script src="./index.js"></script>
// ①.htmlにJSの記述をする
function btn_click() {
  window.alert("クリックされました!")
}

// ②.htmlにJSの記述をしない
window.onload = function() {
  document.getElementById("btn").onclick = function() {
    window.alert("ボタンがクリックされました");
  };
};

ただし、上記の例だと複数のイベントハンドラーを同一イベントに紐づけられない問題点があるため、イベントリスナーを用いる。

イベントリスナーは同一要素の同一イベントに対しても複数紐づけられるイベントハンドラー。

以下で定義。

要素オブジェクト.addEventListener(type※イベントの種類, 処理 ,イベントの方向)

index.htmlとindex.js

<input id="btn" type="button" value="ダイアログ表示"/>

<script src="./index.js"></script>
document.addEventListener('DOMContentLoaded', function(){
  document.getElementById('btn').addEventListener('click',function(){
    window.alert('クリックされました');
  },false);
},false)

🙄正直この例だと上記と同じ処理でイベントリスナーの恩恵はちょっとわかりづらいですが、後述のテキストの取得で恩恵受けている例があります。

✅属性値やテキストの取得と設定

①属性値の取得と更新にsetAttributeメソッド

※シンプルに変数のプロパティに更新することも可能。

index.htmlとindex.js

<a href="https://chobimusic.com"></a>

<script src="./index.js"></script>
var select = document.querySelector("a");
console.log(select.href)

select.setAttribute('href','https://chobimusic.com/select');
console.log(select.href)

開発ツールの出力結果

https://chobimusic.com/
https://chobimusic.com/select

🙄getAttributeメソッドの使い方がいまいちつかめず。

②テキストの取得/更新にinnerHTML/textContentプロパティ

※HTML文字列を埋め込まない(取得しない)場合はtextContentプロパティを優先して利用する。

✋innerHTMLの注意点

下記の例のように、HTMLタグが実行されてしまう(XSS脆弱性)ので、セキュリティ上注意が必要。

<form>
  <textarea id="name" name="name" type="text" ></textarea>
  <div>
    <input id="btn" type="button" value="送信">
  </div>
</form>

<div id="result"></div>

<script>
  document.addEventListener('DOMContentLoaded',function() {
  document.getElementById('btn').addEventListener('click', function() {
    var name = document.getElementById('name');
    var result = document.getElementById('result');
    result.innerHTML = '6月にやることは'+name.value+'です!';
  }, false);
}, false);
</script>

innerHTMLをtextContentに書き換えた場合。

✅スタイルシートの操作

イベントリスナーを使うことで操作できる。

※上記から追記部分のみ記載

<div id="elem">マウスに合わせて色変化</div>
~~~~
document.addEventListener('DOMContentLoaded', function() {
  var elem = document.getElementById('elem');

  elem.addEventListener('mouseover', function() {
    this.style.backgroundColor = 'Yellow';
  }, false);

  elem.addEventListener('mouseout', function(){
    this.style.backgroundColor = '';
  }, false);
}, false);

外部のスタイルシートを適用する際はclassNameプロパティを使用する。

※コード割愛。これを用いることでCSSは.css内に記述できるので可読性が良くなる。

✅ブラウザーオブジェクト

ブラウザー操作のための機能を集めたオブジェクト群の総称。

例)グローバルオブジェクトのWindowオブジェクトやdocumentオブジェクト、XMLHttpRequestオブジェクトなどがある。

アクセス方法

オブジェクト名.reload(); // Window.オブジェクト名.reload();とはしない。

✅Ajax

JavaScript(XMLHttpRequestオブジェクト)を利用してサーバー側と非同期通信を行い、受け取った結果をDOM経由でページに反映する仕組み。

index.htmlとindex.php

<form>
  <input id="name" type="text" name="name" size="15">
  <input id="btn" type="button" name="submit" value="送信">
</form>

<div id="result"></div>

<script>
document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('btn').addEventListener('click', function(){
    var result = document.getElementById('result');
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4) {
        if (xhr.status === 200) {
          result.textContent = xhr.responseText;
        } else {
          result.textContent = "エラー発生";
        }
      } else {
        result.textContent = "通信中・・・";
      }
    };
    xhr.open('GET', 'index.php?name=' +
      encodeURIComponent(document.getElementById('name').value), true);
    xhr.send(null);
  }, false);
}, false);
</script>
<?php
sleep(3);
print('Hello'.$_REQUEST['name'].'さん!');

※3秒後に入力データを元に表示が反映される。

🙄イベントリスナーやここまでの知識をある程度把握しておけばスクリプトの意味も理解できるようになる◎※XAMPPだと文字化けが起こる。。。

✅Promiseオブジェクト

ES6で導入されたJavaScriptの標準組み込みオブジェクトの1つ。Ajaxで起こるコールバック関数地獄を回避できる。

promise.js

function Process(value) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(value) {
        resolve(`入力値:${value}`);
      } else {
        reject('入力値は空です');
      }
    }, 500);
  });
}
Process('トウジロク').then(
  response => {
    console.log(response);
  },
  error => {
    console.log(`エラー:${error}`);
  }
);

コンソールで実行

node promise.js
> 入力値:トウジロク

おわりに

順を追って学習することで非同期処理のスクリプトに対する拒否反応が少なくなった(1文1文理解できるようになったため)。

あとは実際に使いながら覚えていきたいので、使う機会をとりあえず増やしたい。

備忘録

※深掘りできていないもの※

・childNodesプロパティ

要素直下の子ノード群を取得できる。取得したノード群をNodeListオブジェクトとして返す。

コメントを残す