mcpField
A
alpinejs

alpinejs

github.com/brettatoms開発3257 回インストール11 週間前に更新
リポジトリ

alpinejs について

AlpineJSを使う開発者向けの実践ガイドで、ディレクティブ、マジックプロパティ、コンポーネントの構成方法を扱います。HTML属性を短く保ち、複雑な処理を関数や再利用可能なコンポーネント、グローバルストアへ移す方針を示します。

主な機能

  1. 01AlpineJSディレクティブ一覧
  2. 02マジックプロパティの説明
  3. 03複雑な処理の切り出し方
  4. 04再利用可能なコンポーネントとグローバルストア
  5. 05フォーム検証とイベント修飾子の例

活用シーン

  1. 01複雑なインライン処理を含むAlpineJSページの整理
  2. 02複数ページでのコンポーネント再利用
  3. 03共有状態やフォーム操作の管理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/brettatoms/agent-skills --skill alpinejs

インストール後、Claude Code で/alpinejsを入力して読み込まれたか確認します。

詳細

AlpineJS のベストプラクティス

黄金律:属性は短く保つ

HTML 属性に複雑なロジックを記述するのは絶対に避けてください。x-data、x-init、またはその他のディレクティブが約 50 文字を超える場合は、切り出してください。

ディレクティブ早見表

ディレクティブ用途例
x-dataリアクティブなコンポーネントの状態を宣言するx-data="{ open: false }"
x-initコンポーネントの初期化時にコードを実行するx-init="fetchData()"
x-show表示を切り替える(CSS の display)x-show="open"
x-if条件付きでレンダリングする(<template> で囲む必要があります)<template x-if="show">
x-forループする(<template> で囲む必要があります)<template x-for="item in items">
x-bind: / :属性を式にバインドする:class="{ active: isActive }"
x-on: / @イベントをリッスンする@click="open = !open"
x-modelフォーム入力を双方向バインドするx-model="email"
x-textテキストコンテンツを設定するx-text="message"
x-html内部 HTML を設定するx-html="htmlContent"
x-ref$refs を使って要素を参照するx-ref="input"
x-cloakAlpine の初期化が終わるまで非表示にするx-cloak(CSS を追加:[x-cloak] { display: none; })
x-transition入場/退場のトランジションを適用するx-transition または x-transition.duration.300ms
x-effectリアクティブな副作用を実行するx-effect="console.log(count)"
x-ignoreAlpine の初期化をスキップするx-ignore
x-teleport要素を別の場所に移動するx-teleport="#modals"
x-modelable外部からのバインド用にプロパティを公開するx-modelable="value"

マジックプロパティ

プロパティ説明
$el現在の DOM 要素
$refsx-ref を持つ要素にアクセスする
$storeグローバルな Alpine ストアにアクセスする
$watchプロパティの変更を監視する
$dispatchカスタムイベントをディスパッチする
$nextTickDOM の更新後に実行する
$rootコンポーネントのルート要素
$dataコンポーネントのデータオブジェクトにアクセスする
$id一意の ID を生成する

パターン

❌ 悪い例:長いインライン JavaScript

<div x-data="{ items: [], loading: true, error: null, async fetchItems() { this.loading = true; try { const res = await fetch('/api/items'); this.items = await res.json(); } catch (e) { this.error = e.message; } finally { this.loading = false; } } }" x-init="fetchItems()">
✅ 良い例:関数に切り出す
<script>
function itemList() {
  return {
    items: [],
    loading: true,
    error: null,
    
    async fetchItems() {
      this.loading = true;
      try {
        const res = await fetch('/api/items');
        this.items = await res.json();
      } catch (e) {
        this.error = e.message;
      } finally {
        this.loading = false;
      }
    }
  };
}
</script>

<div x-data="itemList()" x-init="fetchItems()">
  
</div>
✅ 良い例:シンプルなインライン状態

<div x-data="{ open: false, count: 0 }">
  <button @click="open = !open">Toggle</button>
  <div x-show="open" x-transition>Content</div>
</div>
✅ 良い例:共有状態にグローバルストアを使う
<script>
document.addEventListener('alpine:init', () => {
  Alpine.store('cart', {
    items: [],
    add(item) { this.items.push(item); },
    get total() { return this.items.reduce((sum, i) => sum + i.price, 0); }
  });
});
</script>

<div x-data>
  <span x-text="$store.cart.total"></span>
</div>
✅ 良い例:Alpine.data() を使った再利用可能なコンポーネント
<script>
document.addEventListener('alpine:init', () => {
  Alpine.data('dropdown', () => ({
    open: false,
    toggle() { this.open = !this.open; },
    close() { this.open = false; }
  }));
});
</script>

<div x-data="dropdown" @click.outside="close()">
  <button @click="toggle()">Menu</button>
  <ul x-show="open" x-transition>
    <li>Item 1</li>
  </ul>
</div>
✅ 良い例:バリデーション付きフォーム
<script>
function contactForm() {
  return {
    email: '',
    message: '',
    errors: {},
    
    validate() {
      this.errors = {};
      if (!this.email.includes('@')) this.errors.email = 'Invalid email';
      if (this.message.length < 10) this.errors.message = 'Too short';
      return Object.keys(this.errors).length === 0;
    },
    
    submit() {
      if (this.validate()) {
        // submit logic
      }
    }
  };
}
</script>

<form x-data="contactForm()" @submit.prevent="submit()">
  <input x-model="email" type="email">
  <span x-show="errors.email" x-text="errors.email" class="error"></span>
  
  <textarea x-model="message"></textarea>
  <span x-show="errors.message" x-text="errors.message" class="error"></span>
  
  <button type="submit">Send</button>
</form>
イベント修飾子
@click.prevent     
@click.stop        
@click.outside     
@click.window      
@click.document    
@click.once        
@click.debounce    
@click.throttle    
@keydown.enter     
@keydown.escape    
トランジション修飾子
x-transition                           
x-transition.duration.300ms            
x-transition.opacity                   
x-transition.scale.90                  
x-transition:enter.duration.500ms      
x-transition:leave.duration.200ms      

すばやく判断するためのガイド

  1. 状態がシンプルなプロパティ 1〜3 個ですか? → インラインで x-data="{ open: false }" を使います
  2. メソッドや複雑なロジックがありますか? → function componentName() { return {...} } に切り出します
  3. 複数のページで再利用しますか? → Alpine.data('name', () => ({...})) を使います
  4. 共有するグローバル状態ですか? → Alpine.store('name', {...}) を使います
  5. 属性文字列が長いですか? → そのやり方は間違っています。切り出してください。

コメント