jQueryが使えない時のJS書き換え

SEO対策の兼ね合いでjQueryの読み込みをやめてVanillaJS（素のJS）に書き換える機会がありました。
その時に調べたことのまとめです。
## DOM操作・取得
### id取得
```
$('#hoge')
              ↓
document.getElementById('hoge')
```
### class取得
```
$('.hoge')
              ↓
document.getElementsByClassName('hoge')
```
HTMLCollectionとして取得します。
### HTMLCollectionの特徴
- 配列に似た感覚で使用できる。 
- forEachは使えない。 
- HTMLCollectionは動的。

### タグで取得
```
$('p')
              ↓
document.getElementsByTagName('p');
```
#### 特定要素内のタグを取得したい場合
```
document.getElementById('hoge').getElementsByTagName('p');
```
HTMLCollectionとして取得します。

### jQueryの感覚で取得（単一）
```
$('.hoge .huga')
              ↓
document.querySelector('.hoge .huga')
```
querySelectorはCSSセレクタで指定できるため、jQueryに近い感覚で取得できます。 
ただし、getElementById等に対してパフォーマンス面で劣ります。 
指定した要素のうち、最初に見つかった要素を1つだけ取得できます。

### jQueryの感覚で取得（複数）

```
<ul>
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>

$('ul li')
              ↓
document.querySelectorAll('ul li')
```
NodeListとして取得します。

#### ・NodeListの特徴
- 配列に似た感覚で使用できる。  
- forEachは使えない。  
- NodeListは静的。  
- HTMLCollectionに対してパフォーマンス面で劣る。  

## 配列
### 取り出し
```
const array = ['a', 'b', 'c'];
$.each(array, function(idx, val){
	〜 処理 〜
});
              ↓
array.forEach(function(val, idx, arr){
	〜 処理 〜
});
```

### forEach等が使用できない場合
HTMLCollectionやNodeListは正式なArrayとは異なるため、そのままでは使用できません。
for文で対応すれば良いのですが、もし使用したい場合は変換する処理が必要です。

```
Array.from(element).forEach(function(val){
  〜 処理 〜
});
```
Array.fromで変換できます、IEには対応していません。

#### IE対応の場合
```
Array.prototype.slice.call(element).forEach(function(val){
	〜 処理 〜
});
```

## イベント
```
element.on('click', function(){
  〜 処理 〜
});
              ↓
element.addEventListener('click', function(){
  〜 処理 〜
});

```
### .on()とaddEventListenerの違い
- .on()はイベント内で重複登録がある。
- addEventListenerは第３引数があり、オプションの使用が可能（capture, once, passive）。  

### jQueryでaddEventListenerを使用
jQueryでDOM取得時はjQueryオブジェクトとして返ってきます。
jQueryオブジェクトに対してaddEventListenerを使用する際はインデックスの指定が必要です。

```
element[0].addEventListener('click', function(){
  〜 処理 〜
});
```

### イベントが重複して登録されてしまうケース
イベント実行時にイベントハンドラ登録をする際は注意が必要です。
addEventListenerだと、こういったことは起こりません。

```
<button id="btn1">ボタン1</button>
<button id="btn2">ボタン2</button>

const func = function(){
  console.log('クリック');
};
$('#btn1').on('click', function(){
  $('#btn2').on('click', func);
});
              ↓
const func = function(){
  console.log('クリック');
};
$('#btn1').on('click', function(){
  $('#btn2')[0].addEventListener('click', func);
});
```

## 属性

### class操作

#### 追加
```
element.addClass('is-active')
              ↓
element.classList.add('is-active');
```

#### 削除
```
element.removeClass('is-active')
              ↓
element.classList.remove('is-active');
```

#### 追加 ~ 削除
```
element.toggleClass('is-active')
              ↓
element.classList.toggle('is-active');
```

### 属性操作

#### 追加
```
element.prop('disabled', true);
              ↓
element.disabled = true;
```

#### 削除
```
element.prop('disabled', false);
              ↓
element.disabled = false;
```

## アニメーション

### フェード
fadeIn等の表現も素のJSでは大変でしたが、CSSを組み合わせることで再現しやすいです。

```
element.fadeIn();
              ↓
element.classList.add('is-active');

// SCSS
element {
  transition: .4s;
  opacity: 0;	
  visibility: hidden;
  &.is-active {
    opacity: 1;
    visibility: visible;
  }
}
```

### スムーススクロール
scroll-behaviorという新しいCSSでページ内リンク推移時のヌルッとした表現が可能です。
ただSafari、IEに対応していません（ポリフィルを使用すれば可能）。

```
html {
  scroll-behavior: smooth;
}
```

あげればきりが無いと思いますが以上となります。 
最後までご覧戴きありがとうございました。