Stimulus3に入門してみた

BasecampがHTMLを拡張するJavaScriptフレームワーク「Stimulus」の最新メジャー版「Stimulus3」を9月24日にリリースしました。
HTMLを主軸にするフレームワークはあまり経験がないのですが面白そうなので、まずは初歩的な使い方から試してゆきたいと思います。
## とにかくすぐに動かしたい
Stimulus公式が提供しているstarter branchがあるので、手っ取り早くgit cloneしてきます。cloneしたあとはnpm packageのインストールも忘れずに。

```bash
$ git clone https://github.com/hotwired/stimulus-starter.git
$ cd stimulus-starter
$ yarn
```
準備が整ったらいよいよ開発用のサーバーを起動しましょう。

```
$ yarn start
```

起動に成功するとターミナルに ```Compiled successfully.``` と表示されます。
![スクリーンショット_2021-10-06_15.31.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/f6df8405-e2fd-9460-9751-72af66b716ec.png)
この時点で ポート9000番 を使用してサーバーが起動していますので、ブラウザーで確認してみましょう。
![スクリーンショット_2021-10-06_15.34.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/a7261c42-1141-43ca-b1ac-595cab64371b.png)
ひとまず無事に動作したところまで確認できました。

## 既存のコードをちょっと改変してみる
StimulusはHTMLファイルとControllerで構成されています。
Controllerは**[Controller名]_controller.js**という命名規則となっており、HTMLからはController名を使用してHTML属性にControllerやイベントを記述してゆく方式です。
![スクリーンショット_2021-10-06_15_16_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/db07d739-971a-aa7c-af79-0635c9d68fe6.png)
以下のようにHTMLでexample-controller.jsを指定している。
![スクリーンショット_2021-10-06_15_16_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/a41b9f1a-3d45-813d-821c-e383e23dfac1.png)
ということなので、example2というControllerを作ってみます。
![スクリーンショット_2021-10-06_15.53.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/3d9b7338-3683-71af-1227-7d6d3d6145f6.png)
HTMLにもexample2を定義します。
![スクリーンショット_2021-10-06_15.52.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/54e40998-db93-30a0-b9dc-9a321c40eb6d.png)
example2が動きました！
![スクリーンショット_2021-10-06_15.55.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/adbd30e4-5234-30fe-a272-fd55a59cc9a0.png)
## ボタンクリックイベントと要素へのアクセス
クリックイベントと要素へのアクセスができればあとは応用でなんとかなる！という信念があるので、一気に両方試してみましょう。
### ソースコードの改変
まずはHTMLにテキスト入力フォームとボタンを用意します。また、入力された文字列を表示するためのdivタグも用意します。

**index.html**

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <link rel="stylesheet" href="main.css" />
    <script src="bundle.js" async></script>
  </head>
  <body>
    <h1 data-controller="example"></h1>

    <div data-controller="example2">
      <input data-example2-target="name" type="text" />
      <button data-action="click->example2#greet">Greet</button>
      <div
        data-example2-target="nameDisplay"
        style="color: #f00; margin-top: 1rem"
      ></div>
    </div>
  </body>
</html>
```

Controllerの中も色々変えていきます。

**src/controllers/example2_controller.js**

```js
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
  // targetとして使用する要素を予め定義する
  static targets = ['name', 'nameDisplay'];

  // greetボタンが押されたときのイベント関数
  greet() {
    // Divタグの中に入力された文字列を表示する
    this.nameDisplayTarget.textContent = this.name;
  }

  // 入力フォームのgetter
  get name() {
    return this.nameTarget.value;
  }
}
```

Stimulusは命名規則でHTMLとControllerを繋ぐ仕組みなので、ターゲット要素も命名規則によって定義します。

```
data-[Controller名]-target="[ターゲット要素名]"
```

同様にボタンのクリックイベントも以下のように定義します。

```
data-action="click->[Controller名]#[関数名]"
```

### ブラウザーで動かしてみる
入力値をクリックイベントで画面表示することに成功しました！
![画面収録_2021-10-06_16.19.33.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2221418/b043bbba-567a-0768-a7a6-031a9caa0948.gif)
## まとめ
HTMLとJavaScriptを繋ぐ方法として「on〜」のようなイベントリスナーを定義する手法が一般的ですが、Stimulusは命名規則を使用することでHTMLを主軸にControllerを操作するアプローチが図られています。リスナー定義がなくなるだけでJavaScriptのソースコードがとてもシンプルになりました。ただ代わりにHTMLに多くの属性を記述することになるのでHTMLソースの可読性は低下した気がします。
あと、特徴的な命名規則のせいでHTMLソースを覗かれるとStimulusを使用していることがバレバレです。

ちなみにStimulusはMutationObserverによってDOMの変更を検知して自動的にAttachしてくれるようなので、別のフレームワークやライブラリと組み合わせても使えそうですね。

以上