ドロワーメニューをJSのClass構文で書いてみた

こんにちは。
最近はJavaScriptを強化したくて、少しずつJavaScriptを学習しています。
そんな中、クラス構文を学び、使用頻度の高いドロワーメニューに活かしてみようと思ったので、自分の学びとして記事に残したく、初めてですが記事を書いていきます。

# 1.今までの書き方

これまでは下記のようにjQueryにて書いていました。
「js-drawer」クラスをクリックすると、bodyに「is-drawerActive」クラスが付与されて、その時にドロワーメニューが出てくる仕組みになっています。

```js:
$(function() {
  // ドロワーメニュー
  $('.js-drawer').click(function() {
    $('body').toggleClass('is-drawerActive');

    if($(this).attr('aria-expanded') == 'false') {
      $(this).attr('aria-expanded', true);
    } else {
      $(this).attr('aria-expanded', false);
    }
  });
});
```

ちなみにですが、この時のhtmlファイルは下記になります。
aria-controls属性とaria-expanded属性についてはアクセシビリティを考慮して記入しています。

```html:
      <nav class="l-header-nav">
        <h2 class="screen-reader-text">サイト内メニュー</h2>
        <button type="button" class="js-drawer button-hamburger" aria-controls="global-nav"
          aria-expanded="false">
          <span class="hamburger">
            <span class="screen-reader-text">メニュー開閉する</span>
          </span>
        </button>
        <ul id="global-nav" class="l-global-nav">
          <li class="global-nav-item">
            <a href="#">メニュー</a>
          </li>
          <li class="global-nav-item">
            <a href="#">メニュー</a>
          </li>
          <li class="global-nav-item">
            <a href="#">メニュー</a>
          </li>
        </ul>
      </nav>
```

# 2.Class構文での書き方
これまでのドロワーメニューの書き方を下記のClass構文の書き方へ書き換えました。
```js:
class Toggle {
  constructor(selector, target) {
    this.btn = document.querySelector(selector);
    this.target = document.querySelector(target);
    this.objectName = selector.substring(4);

    this.btn.addEventListener("click", this._toggle.bind(this));
  }

  _toggle() {
    // aria-expanded 属性の切り替え
    const isExpanded = this.btn.getAttribute("aria-expanded") !== "false";
    this.btn.setAttribute("aria-expanded", !isExpanded);

    // this.targetにクラスを付与
    this.target.classList.toggle(`is-${this.objectName}Active`);
  }
}

new Toggle(".js-drawer", "html");
```

上記書き方の手順について少し説明していきます。

## 2.1 Classを定義し、インスタンス化を行う
Class構文を書くにあたり、まずは下記の書き方を知っておく必要があります。
```js:
class クラス名 {
    constructor([引数, ... ]) {
        this.プロパティ = 値;
    }

    メソッド([引数, ... ]) {

    }
}
new クラス名();

```
今回のドロワーメニューでは、クラス名をToggleと定義しました。
クラス名は自由に決めてもらって大丈夫です。

## 2.2 コンストラクタ関数内にプロパティを定義していく
Classを定義した後は、コンストラクタ関数内にプロパティを定義していきます。
```js:
class Toggle {
  constructor(selector, target) {
    this.btn = document.querySelector(selector);
    this.target = document.querySelector(target);
    this.objectName = selector.substring(4);
  }
}

new Toggle(".js-drawer", "html");
```
Classの第一引数にはドロワーメニューであるbuttonタグに記入しているクラス名を、第二引数にはクリックした時にクラス名を付与する場所を記入しています。

今回の場合ですと、「.js-drawer」を記入しているbuttonタグをクリックしたときにhtmlタグに任意のクラス名を付与したいので、第一引数には「.js-drawer」を、第二引数にはhtmlを指定しています。
第二引数である"html"の部分を"body"に変更すると、bodyタグに任意のクラス名が付与されることになります。

プロパティが少しわかりにくい場合は、下記のようにそれぞれをconsole.logで出力してみてください。一つずつconsole.logで確認していくことで、エラーが起きた際にも何が原因なのかすぐにわかるため、自分もしつこいくらいconsole.logで確認することを意識しています。

```js:
class Toggle {
  constructor(selector, target) {
    this.btn = document.querySelector(selector);
    console.log(this.btn); // .js-drawer

    this.target = document.querySelector(target);
    console.log(this.target); // html

    this.objectName = selector.substring(4);
    console.log(this.objectName); // drawer
  }
}

new Toggle(".js-drawer", "html");
```

## 2.3 メソッドを定義する
プロパティを定義した後は、メソッドを定義していきます。
```js:
  _toggle() {
    // aria-expanded 属性の切り替え
    const isExpanded = this.btn.getAttribute("aria-expanded") !== "false";
    this.btn.setAttribute("aria-expanded", !isExpanded);

    // this.targetにクラスを付与
    this.target.classList.toggle(`is-${this.objectName}Active`);
  }
```
aria-expanded属性は、メニューが表示されている時には"true"を、メニューが隠れている時には"false"にしてくれるように書いています。

## 2.4 クリックイベントを書く
メソッドを定義した後はクリックイベントを下記のように書いていきます。
```js:
    this.btn.addEventListener("click", this._toggle.bind(this));
```
bindメソッドを使用し、thisの束縛をしています。
このthisの束縛をしなければ、メニューが開いてくれないため、注意が必要です。

あとは、上記のクリックイベントをコンストラクタ関数内に記入すれば完成です。

```js:
class Toggle {
  constructor(selector, target) {
    this.btn = document.querySelector(selector);
    this.target = document.querySelector(target);
    this.objectName = selector.substring(4);


    this.btn.addEventListener("click", this._toggle.bind(this));
  }

  _toggle() {
    // aria-expanded 属性の切り替え
    const isExpanded = this.btn.getAttribute("aria-expanded") !== "false";
    this.btn.setAttribute("aria-expanded", !isExpanded);

    // this.targetにクラスを付与
    this.target.classList.toggle(`is-${this.objectName}Active`);
  }
}

new Toggle(".js-drawer", "html");

```

JSは凄く難しいですが、今までのコードをJSに書き換えて上手く動いた時は感動ですね。
もっと色んなものをJSで書けるように学習していきます。