Open10

Alpine.jsを触ってみた

MMMMMM

Alpine.jsを使ってみる

4連休だけど結局緊急事態宣言だったりで何もすることがないので新しい技術(ほぼVue.jsと同等なので新しい学びかと言われれば微妙だけど)をちょろっと学習する

Alpine.js(Github repository)

MMMMMM

Alipine.js is 何

ちょうど一年半前くらいにGithubのトレンドになったJSのフレームワーク。
Vueライクなディレクティブを使えるが、Vueなどに比べると軽量かつ学習コストが低そう(15のディレクティブから成っている、機能がかなり絞り込まれている)。
大規模なアプリ作成というよりLP的なものだったり軽いアプリを作りたいが、Vue.jsやReact.js、Nuxt.jsだったりを使うのはちょっと微妙、だけどデータバインドとかはしたい時にサクッと使える気がする。
CDNで読み込み、もしくはnpm install alpineでもできるらしい(npmの方はやってない)。
ちなみに今回はCDNでサクッと体験。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.3.5/dist/alpine.min.js" defer></script>
  <title>alpine.jsを使ってみよう!!!</title>
</head>
<body>
</body>
</html>

読み込む時は<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js" defer></script>のようにバージョン箇所をxを使うことができるらしいが、動作が安定しないので特定のバージョンを指定する方が良いらしい。
ちなみにリリースノートを見た感じは3.2.2が最新バージョンでした。

MMMMMM

x-data

Vue.jsでのdataにあたるディレクティブ。
x-dataにオブジェクト形式でデータを書き込むとその要素と要素内で使うことができる。

<div x-data="{ sampleText: "test" }">
  <p x-text="sampleText"></p>
</div>

上記の結果としてはtestがpタグのテキストとして出力される。

ちなみにx-dataはインラインでオブジェクトを渡すだけでなくて、関数を渡して、returnの値に使用したいデータを記載することも可能。

<!-- ここでtestFunctionを呼ぶことで、testFunction配下でreturnされているsampleTextとchangeTextが使える -->
<div x-data="testFunction()">
  <p x-text="sampleText"></p>
  <button @click="changeText()">文字列変更!!!</button>
</div>
<script>
  const testFunction = () => {
    return {
      sampleText: 'test',
      changeText() {
        this.sampleText = 'changed'
      },
    }
  }
</script>

ついでにここでx-textについても紹介。
これについては特に難しくなくて、Vue.jsでいうなら{{ }}、つまりテンプレート構文と同様の使い方。
テキストがリアクティブに変更されるときに、テンプレート構文が存在しないので、その代わりにx-textで対応している、程度の認識で大丈夫です。

MMMMMM

x-on

実はすでにでてる。

<div x-data="testFunction()">
  <p x-text="sampleText"></p>
  <!-- ここの@clickのこと -->
  <button @click="changeText()">文字列変更!!!</button>
</div>
<script>
  const testFunction = () => {
    return {
      sampleText: 'test',
      changeText() {
        this.sampleText = 'changed'
      },
    }
  }
</script>

上の例は省略形だが、

<div x-on:[event]="function"></div>

という書き方でクリックだったりマウスオーバーのイベントを監視できる(Vueをわかっていればそのままって感じの印象)。

MMMMMM

x-show

Vue.jsでいうところのv-showと同じ。
x-showにtrue/falseを持たせて、該当の要素を表示/表示させます。

<div x-data="{ isShow: true }">
  <p x-show="isShow">表示してます</p>
  <button @click="isShow = !isShow">表示変更</button>
</div>

上記はx-showisShowをデータとして持たせ、ボタンの押下で表示/非表示を行っています。
こちらは単純にdisplay: noneが属性として付与されるだけなので、もしDOM自体から要素を減らしたいのであれば後述のx-ifを使います。

個人的なメモ:要素の出す出さないを画面でコントロールができる場合にはx-showを使うべきだと思っています。理由としてはDOM要素を消したり戻したりをするより、x-showをを使う単純なCSSの属性付与による見せかけの表示制御の方が理にかなっているので。
ただDOM要素が削減されないという点では表示なりで問題もありそうな気もするので、ここだけは考えどころかもしれない。

MMMMMM

x-bind / x-model

どちらもxをvに変えればVueのものと同じイメージです。
x-bindは親要素→子要素の一方通行なデータの使い方、x-modelは親要素と子要素で双方向的なデータの取り扱いができます。

<div x-data="{ testText: 'sample' }">
  <!-- x-bindによる一方的な流し込み -->
  <input type="text" x-bind:placeholder="testText">
  <!-- x-moelによる双方向のデータのやりとり -->
  <input type="text" x-model="testText">
</div>

1つ目のinputについては、placeholderx-bindを使ってtestTextを表示するようにしています(ちなみにx-bindは:と省略可能です)。
そのため、いくらinputにテキストを入れても変更は発生しません。
2つ目のinputではx-modelとしてtestTextを指定しています。
そのため、2つ目のinputでテキストを変更すると、1つ目のinputに指定したplaceholderの文字が変わることが確認できると思います。

MMMMMM

x-ref

Vueでいうところのref
x-bindと異なり、$refsを使うことで値に直接アクセスが可能になる。

<div x-data="{ refsText: 'aaa' }">
  <input type="text" x-model="refsText" x-ref="textInput">
  <p x-text="$refs.textInput.value"></p>
</div>

なぜかCDNのバージョン2.3.5では同一の要素内でしかrefを参照できず、x-bindと親しきものになってしまっていた。

ちなみにrefは簡単にいうとコンポーネントへの参照IDの振り分けというイメージ。
emitの逆で、子のコンポーネントの関数などを呼び出したかったりするときにrefを子コンポーネントへ付与、Vueではthis.$refs.XXXのような形で子のコンポーネントへのアクセスを行う。

MMMMMM

x-if

templateタグに対して使える?(pタグなどでは挙動を確認できず)
x-showと異なり、要素そのものをDOMから非表示にする。

<div x-data="{ isShow: true }">
  <template x-if="isShow">
    <div>
      テスト
    </div>
  </template>
  <button @click="isShow = !isShow">表示変更</button>
</div>

上記の場合には<template x-if="isShow"></div>に囲われたエリアに変化がある。

MMMMMM

x-init

Vueでいうところのcreated。
DOMの初期更新時にイベントを発生させることができる。
2.3.5のバージョンではx-dataが同じ要素に記載されている必要がある。

<div x-data x-init="initializedEvent()"></div>
<script>
const mounted = () => {
    alert("mounted相当のタイミングで実行、DOM初期化済")
  };
  const initializedEvent = () => {
    alert("initialized!!!");
    // returnに記載されたものについては、mounted相当のタイミングで実行される
    return mounted;
  }
</script>
MMMMMM

Magics

今までで出ているものだと$refsがこれに相当する。
その他にもいくつかのプロパティがあるので、公式を参照してください(挫折)。