Open16

Alpine.js やる

高校の卒業研究でWebアプリを作っている。技術について学習コストを考慮に入れるのはあまり好きではないのだが、メンバーの環境にBabelをセットアップしたりするのがあまりやりたくないという気持ちがあり、HTMLにテンプレート書いてライブラリを読み込めばサクッと動くというようなものが欲しい。

個人的にはReactでJSXを使って式をガチャガチャするのが好きなのだが、ライブラリ直に読み込むような場面ではJSXが使えずReact.createElementを手書きすることになって心が温まるのであまり向いていないと思う。そこでVueやAlpineはHTMLにテンプレート書いてライブラリ読み込んで<script>にふるまい書けば動くっぽそうなのでそれを使ってみたいなあという気がしています。ゆえにAlpineをやる。

とりあえず開発サーバーはどうしても必要になってしまう。@web/dev-server に全幅の信頼を置いている。

  "name": "alpine-de-asobu",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "start": "web-dev-server --watch --root-dir dist/"
  },
  "license": "CC0",
  "devDependencies": {
    "@web/dev-server": "^0.1.24",
    "prettier": "^2.4.1"
  }
}

Alpine本体をCDNから入れた方がいいか、npmから入れてしまうかには考える余地があるかも。

ふむ。

<!DOCTYPE html>
<html lang="ja">
  <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" />
    <title>Alpine test</title>
    <script
      defer
      src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"
    ></script>
  </head>
  <body>
    <script type="module"></script>
    <h1 x-data="{ message: 'Hello Alpine.js!' }" x-text="message"></h1>
  </body>
</html>

インテリセンスあるとはいえちょっと文字列ベタ書きはあまりうれしくない。

Alpine公式サイトにはちゃんとシンタックスハイライト効いてるのずるい。おれのVSCodeにもくれ。

x-data="{ count:0 }" とするとその要素以下のディレクティブでcountが使えるようになる。count が変更されるとそれを使っているディレクティブみんな反映される。

x-on:click="count++" とするとその要素がクリックされたとき count++ する。この count は上で定義したやつ。省略形として @click="count++" と書くこともできる。

x-text="count" と書くとJavaScript式を評価した結果がその要素の子のテキストノードになる。

<div x-data="{ open: false }">
      <button @click="open = !open">Toggle</button>
      <div x-show="open" @click.outside="open = false">hidden content</div>
    </div>

x-show="expr" とするとexprがtrueのとき表示、falseのとき非表示。ずいぶん高レイヤーな機能だ。

@click.outside とすると その要素の外側をクリックしたときのイベントを使える。すげえ。

getterを使う例。

  <div
      x-data="{
      search: '',
      items: ['foo', 'bar', 'baz'],
      get filteredItems () {
        return this.items.filter(item => item.startsWith(this.search))
      }
    }"
    >
      <input x-model="search" placeholder="search..." />
      <ul>
        <template x-for="item in filteredItems" :key="item">
          <li x-text="item"></li>
        </template>
      </ul>
    </div>

<input x-model="search">とするとsearchとinputの双方向バインディングができる。

Vueでいうcomputed propertyをgetterでやっている。

<template x-for="束縛する変数 in 配列"> でループできる。 <template> を使うのが面白い。

        <template x-for="item in filteredItems" :key="item">
          <li x-text="item"></li>
        </template>
ログインするとコメントできます