【脱jQuery】モダンなJSの書き方

# はじめに

普段、Ruby On RailsでMPA（マルチページアプリケーション）による開発をメインに行っています。
最近「jQueryを使わない」という話しをチラホラ見かけるようになりました。その辺を調べていくうちに自分も「jQueryを使うのやめよう」と思いました。しかし、jQueryに慣れてしまっていて、プレーンなJSで書く方法がパッと出てこなかったので、その辺りを備忘録としてまとめてみました。


# jQueryでよく使っていた機能

自社内のプロダクトでjQueryの利用状況をざっと見たところ、利用されている機能としては次のものが多かったです。

- セレクタ
- Ajax
- イベント
- ループ

それぞれプレーンJSでの記述例を書いておきます。


# 単一セレクタの例

##### jQuery
```js
const title = $("#title");
```

##### プレーンJS
```js
const title = document.querySelector("#title");
```

# 複数セレクタとループの例

##### jQuery
```js
const list = $(".list");
$.each(list, function(index, item){
    console.log($(item).text());
});
```

##### プレーンJS
```js
const list = document.querySelectorAll(".list");
list.forEach(function(item) {
    console.log(item.innerHTML);
});
```

# イベントの例

##### jQuery
```js
$(".list").click(function(){
    console.log($(this).text());
});
```

##### プレーンJS
```js
document.addEventListener("click", function(event) {
    console.log(event.target.innerHTML);
}, false);
```

# Ajaxの例

##### jQuery
```js
$.ajax('/test_data.json'
)
.done(function(data) {
    console.log(data);
})
.fail(function() {
    console.log("エラー");
});
```

##### プレーンJS
```js
fetch("/test_data.json")
.then(response => {
    return response.json();
})
.then(data => {
    console.log(data);
})
.catch(error => {
    console.log("エラー");
});
```

---


# プレーンJSのサンプルコード

```plane_js.html
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id = "title" >タイトル</div>
<ul>
	<ui class = "list" >リスト1</ui>
	<ui class = "list" >リスト2</ui>
	<ui class = "list" >リスト3</ui>
</ul>
<div data-value = "123" >データタグ</div>
</body>
<script type="text/javascript">
	// セレクタ：単一
	const title = document.querySelector("#title");
	console.log(title.innerHTML);

	// セレクタ：複数　と　ループ
	const list = document.querySelectorAll(".list");
	list.forEach(function(item) {
		console.log(item.innerHTML);
	});

	// イベント：リスト1、リスト2、リスト3につける
	document.querySelectorAll(".list").forEach(function(ui) {
		ui.addEventListener("click", function(event) {
			console.log(event.target.innerHTML);
		}, false);
	});

	// データ属性
	const value = document.querySelectorAll('[data-value="123"]');
	console.log(value[0].innerHTML);

	// Ajax
	fetch("/test_data.json")
  	.then(response => {
    	return response.json();
  	})
  	.then(data => {
    	console.log(data);
  	})
  	.catch(error => {
    	console.log("エラー");
	});

</script>
</html>
```

```test_data.json
{ "name": "テストデータ" }
```


# コンソール出力例

```text
タイトル
リスト1
リスト2
リスト3
データタグ
{name: 'テストデータ'}
```

# jQueryのサンプルコード

```jquery_js.html
<html>
<head>
<script src="https://code.jquery.com/jquery-3.6.1.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id = "title" >タイトル</div>
<ul>
	<ui class = "list" >リスト1</ui>
	<ui class = "list" >リスト2</ui>
	<ui class = "list" >リスト3</ui>
</ul>
<div data-value = "123" >データタグ</div>
</body>
<script type="text/javascript">
	// セレクタ：単一
	const title = $("#title");
	console.log(title.text());

	// セレクタ：複数　と　ループ
	const list = $(".list");
	$.each(list, function(index, item){
		console.log($(item).text());
	});

	// イベント：リスト1、リスト2、リスト3につける
	$(".list").click(function(){
    	console.log($(this).text());
	});

	// データ属性
	console.log($('[data-value="123"]').text());

	// Ajax
	$.ajax('/test_data.json'
	)
	.done(function(data) {
		console.log(data);
	})
	.fail(function() {
		console.log("エラー");
	});

</script>
</html>
```


# jQuery時代に書いたコードでありがちなこと

### データ属性
MDNには「特定の要素を選択したり特定の要素にアクセスしたりすることを可能にします。(中略)仕様書ではクラス名の要件を示していませんが、ウェブ開発者は要素の外見ではなく、意味論的な目的を表す名前を使用することが推奨されます。」
とのことですので、訂正いたします。

@NagayamaToshiakiさんにご指摘いただきました。ありがとうございます。


~~本来ならデータ属性で指定すべきものを、CSSクラスとして設定しておいてセレクタに使っている。~~
~~CSSクラスは見た目のデザインに関するものなので、ロジックに使うものはデータ属性やID、NAMEなどを使いたいところ。~~



```html

/* jQueryでクラス指定 */
<div class='click-element-1'>クリックして！</div>
$('.click-element-1').on('click', function() ...


/* データ属性 */
<div data-element-type='click'>クリックして！</div>
click_element = document.querySelector("[data-element-type='click-element-1']");
click_element.addEventListener ...

```

~~IE10以下でデータ属性がサポートされていなかった。attr()でデータ属性使えたけど、クラスやIDセレクタと書き方が異なることや、データ属性へのアクセス速度が遅かったことなどからこのような実装が広まったのかもしれません。（自社内で）~~


### AjaxとRails

自社ではRailsを使って開発をしています。Railsのform-withを使えば基本的にはJSでAjaxを記述する必要はないのですが、どうしてもJSでAjaxを記述する必要のある箇所にはfetchを使っていこうと考えています。



# サンプルの確認

上記のJSの動作を確認しようとしてローカルファイルを直接ブラウザで開くと、Ajaxを動かそうとして「CORS policy」エラーとなります。

```
Access to fetch at 'file:///test_data.json' from origin 'null' has been 
blocked by CORS policy: Cross origin requests are only supported for protocol schemes:
http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.
```


Macの場合、ターミナルで該当htmlがあるフォルダに移動して次のコマンドを実行

```text
python -m http.server 8888
```

ブラウザから
http://localhost:8888/ファイル名/
でページにアクセスできるようになります。


# 最後に

[Rails5.1：jQuery非依存の記事 ](https://github.com/rails/rails/pull/27113)
[BootStrap：jQuery非依存の記事](https://www.infoq.com/jp/news/2020/08/bootsrap-5-drops-jquery/)

他にも「jQuery 終わった」などで検索すると沢山の情報にヒットします。

IEのサポートが終了して、ES6をサポートしたモダンなブラウザだけをサポートすれば良くなった昨今のブラウザ事情が脱jQueryの大きな理由のようです。

IEのサポートが終わって本当に良かったと思います。