🦓

Alpine.js ディレクティブ&マジックプロパティ

2023/12/03に公開

はじめに

Alpine.jsは、軽量でシンプルなJavaScriptフレームワークであり、HTMLにインラインで記述されたJavaScriptを使用して要素に動的な動きをつけることができます。
大規模なプロジェクトや複雑な状態管理が必要な場合は、Vue.jsやReactを検討することが多いですが、小規模なプロジェクトやSPA的なUIの構築にはAlpine.jsをおすすめします。

https://alpinejs.dev/start-here

Alpine.jsの特徴

Alpine.jsは、HTML内でデータとUIを簡潔に結びつけ、データの変更に応じてUIが自動的に更新されるリアクティブデータバインディングを提供しています。
また、要素の表示や非表示、追加、削除などのトランジションとアニメーションをサポートする組み込みの機能があります。
CDNを読み込むだけでプロジェクトに組み込めるのでフロントの構築がスムーズに行えます。

Alpine.jsを導入する

html<head>タグ内に追加します。

<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>

パッケージマネジャーからのインストールも可能です。
https://alpinejs.dev/essentials/installation#as-a-module

ディレクティブ(Directives)

HTMLにインラインでJavaScriptを埋め込むことで、特定の要素に対して機能を追加できるディレクティブを提供します。例えば、x-dataディレクティブはデータを要素にバインドし、x-showディレクティブは要素の表示/非表示を切り替えるために使用されます。Alpineは18個のディレクティブを提供しています。

ディレクティブ 説明
x-data コンポーネントにデータをバインドするディレクティブ。
x-init コンポーネントの初期化時に実行されるJavaScriptコードを指定するディレクティブ。
x-show 要素の表示/非表示を切り替えるディレクティブ。
x-bind 要素の属性やプロパティにデータをバインドするディレクティブ。
x-on イベントハンドリングを設定するディレクティブ。
x-text テキストコンテンツを設定するディレクティブ。
x-html HTMLコンテンツを設定するディレクティブ。
x-model フォーム要素の値を双方向データバインドするディレクティブ。
x-modelable モデル可能な要素に自動的にx-modelを追加するディレクティブ。
x-for リストの反復処理を行うディレクティブ。
x-transition 要素のトランジションやアニメーションを設定するディレクティブ。
x-effect モデルが変更されたときに自動的に実行されるコードを設定するディレクティブ。
x-ignore 要素をAlpine.jsのトラッキング対象から除外するディレクティブ。
x-ref 要素に参照を設定するディレクティブ。
x-cloak コンポーネントが初期化されるまで要素を非表示にするディレクティブ。
x-teleport 要素をDOMの別の場所にテレポート(移動)するディレクティブ。
x-if 条件に基づいて要素の表示を切り替えるディレクティブ。
x-id 要素に一意のIDを設定するディレクティブ。

x-data

x-dataは、HTMLの一部をAlpineコンポーネントとして定義し、そのコンポーネントが参照するためのリアクティブデータを提供します。

<div x-data="{ message: 'Hello, Alpine.js!' }" x-text="message">
</div>

x-dataディレクティブ内にJavaScriptオブジェクトがあり、そのオブジェクトのプロパティと値がコンポーネントのデータとしてバインドされます。
このデータは、その要素の範囲内のみ有効です。

x-textはAlpine.jsによってバインドされたデータのテキスト内容を表示します。データが変更されると、自動的にUIも更新されます。

https://alpinejs.dev/directives/data
https://alpinejs.dev/directives/text

x-show

{open: false}は要素を非表示にする初期設定です。
x-onは、ディスパッチされたDOMイベントに対してコードを実行するディレクティブです。ここではクリックイベントに対してopenの状態を切り替える実行されます。
x-showディレクティブは要素の表示/非表示を切り替える時に使います。
x-show="open"openの状態をtrueに設定し、要素を表示させます。
x-transitionはトランジションを追加するヘルパーです。

<div x-data="{ open: false }">
    <button x-on:click="open = !open">トグル
    </button>

    <div x-show="open" x-transition>
        <p>テキスト</p>
    </div>
</div>
# どちらでも大丈夫
x-on:click="open = !open"
@click="open = !open"

https://alpinejs.dev/directives/show
https://alpinejs.dev/directives/transition#the-transition-helper

x-effect

x-effect は、依存関係が変更されたときに式を再評価するのに便利なディレクティブです。どのプロパティを監視するかを指定する必要がなく、その中で使用されているすべてのプロパティを監視するウォッチャーと考えることができます。

<div x-effect="console.log(open)"></div>

トグルボタンをクリックし、console.logの内容が動的に表示されていることを確認します。
https://alpinejs.dev/directives/effect

x-bind

x-bindでは、JavaScriptの式の結果に基づいて要素にHTML属性を設定することができます。
要素の表示/非表示状態によってトグルボタンのクラスを切り替えます。

# どちらでも大丈夫
x-bind:class="open ? 'bg-indigo-400' : 'bg-slate-400'"
:class="open ? 'bg-indigo-400' : 'bg-slate-400'"

https://alpinejs.dev/directives/bind

x-model

x-modelでは、入力要素の値をAlpineのデータにバインドすることができます。

<div x-data="{ message: '' }">
    <input type="text" x-model="message" placeholder="検索">
     
    <div x-text="message"></div>
</div>

Image from Gyazo

https://alpinejs.dev/directives/model

x-if

x-ifは、x-showと同様にページ上の要素をトグルするために使われるが、CSSのdisplayプロパティを "none"に変更するだけではなく、適用された要素を完全に追加・削除することになります。

x-showとは異なり、x-ifはx-transitionによるトグルの遷移をサポートしていません。

<div x-data="{ open: false }">
    <button x-on:click="open = !open">トグル
    </button>

    <template x-if="open">
        <div>コンテンツ</div>
    </template>
</div>

https://alpinejs.dev/directives/if

x-for

x-forディレクティブを使うと、リストを繰り返し処理してDOM要素を作成できます。
配列に基づいて色のリストを作成していきます。

<ul x-data="{ colors: ['Red', 'Orange', 'Yellow'] }">
    <template x-for="color in colors">
        <li x-text="color"></li>
    </template>
</ul>

DOMにリストを作られていることを確認します。

https://alpinejs.dev/directives/for

x-ref

x-ref と $refs の組み合わせは、getElementByIdquerySelectorのようなAPIの代わりとしてDOM 要素に簡単に直接アクセスできるようになります。

<button @click="$refs.text.innerText = 'Hello 👋'">Hello</button>
<p x-ref="text"></p>

Image from Gyazo

https://alpinejs.dev/directives/ref

x-html

x-htmlは、要素のinnerHTMLプロパティを、与えられた式の結果に設定します。

<div x-data="{ username: '<strong>田中</strong>' }">
   ユーザー名: <span x-html="username"></span>
</div>

https://alpinejs.dev/directives/html

「マジックプロパティ」(Magic Properties)

マジックプロパティは、特殊な変数です。コンポーネント内で異なる操作や情報にアクセスするために使用されます。特にイベントハンドリングや動的なクラスの切り替えなど、コンポーネント内で様々な操作を行う際に便利です。Alpineは9個のマジックプロパティを提供しています。

マジックプロパティ 説明
$el 現在のコンポーネントに関連付けられているDOM要素への参照。
$refs コンポーネント内で特定の要素にアクセスするための参照を保持するオブジェクト。
$store コンポーネントが登録された親コンポーネント(x-data内で使用されたコンポーネント)のデータストアへの参照。
$watch コンポーネントのデータやプロパティの変更を監視するための関数。
$dispatch イベントを上位の親コンポーネントにディスパッチするための関数。
$nextTick 次のDOM更新サイクルで実行されるコールバックをスケジュールする関数。
$root コンポーネントツリーのルートである親コンポーネントへの参照。
$data コンポーネントにバインドされているデータオブジェクトへの参照。
$id コンポーネントに割り当てられた一意のID。

$el

$elは、現在のDOMノードを取得するために使用できるマジックプロパティです。

<div x-data>
    <button 
        x-on:click="$el.innerHTML = 'Hello World'">
            Click
    </button>
</div>

Image from Gyazo

https://alpinejs.dev/magics/el

$watch

$watchは、指定したデータプロパティを監視し、その値が変更されたときに特定のアクションを実行することができます。

<div x-data="{ myVar: 'Initial Value' }">
    <input x-model="myVar">
    <button @click="$watch('myVar', newValue => console.log(newValue))">
        Watch 'myVar'
    </button>
</div>

$watchディレクティブはmyVarというデータプロパティを監視しています。ユーザーがinputフィールドに値を入力すると、$watchが呼び出され、入力値に対してconsole.logで出力する処理を行います。

Image from Gyazo

https://alpinejs.dev/magics/watch

$dispatch

dispatchは、ブラウザのイベントをディスパッチするためのプロパティです。

<div x-data @notify="alert('Hello World!')">
    <button @click="$dispatch('notify')">
            Notify
    </button>
</div>

https://alpinejs.dev/magics/dispatch

$data

$dataは現在のAlpineのdataスコープ(x-dataで提供される)にアクセスできるプロパティです。

ほとんどの場合、式の中で直接Alpineのデータにアクセスすることができます。
例えば、x-data="{ message: 'Hello Caleb!'"}とすると、x-text="message"のようになります。

しかし、すべてのスコープをカプセル化した実際のオブジェクトがあると、他の関数に渡すときに便利なことがあります。

<div x-data="{ greeting: 'Hello' }">
    <div x-data="{ name: 'Caleb' }">
        <button @click="sayHello($data)">Say Hello</button>
    </div>
</div>
<script>
    function sayHello({ greeting, name }) {
        alert(greeting + ' ' + name + '!')
    }
</script>

まとめ

Alpine.jsのディレクティブとマジックプロパティをいくつか使ってみました。
HTMLに直接記述されるJavaScriptとディレクティブの構文を使用するだけで動的なUIを構築することができて便利です!

Discussion