WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

@wcstack/stateでHTMLにリアクティブ状態管理|ビルドレスでDOM自動更新を実装する方法

生徒

ReactやVueを使わずに、HTMLだけで「値が変わったら画面が自動更新される」仕組みって作れますか?

ペン博士

それを実現するのが @wcstack/state じゃ!CDNを1行読み込むだけで、ビルドツールもnpm installも不要でリアクティブなHTMLが書けるんじゃ。data-wcs属性で状態とDOMを繋ぐだけで、カウンター・双方向バインディング・リスト表示・条件分岐まで実装できるぞ!

目次

この記事でわかること

  • @wcstack/state の概要と内部の仕組み(ES Proxy・Direct DOM更新)
  • CDN1行によるセットアップ方法と基本の書き方(wcs-stateタグ・data-wcs属性)
  • 双方向バインディング・リスト表示(for)・条件分岐(if/elseif/else)の実装方法
  • 組み込みフィルタ40種類の使い方
  • Alpine.js・React・Vueとの違いと、向いているユースケース

@wcstack/stateとは|フレームワークなしのリアクティブHTML

@wcstack/stateは、HTMLファイル1つで「値が変わったらDOMが自動で更新される」リアクティブな仕組みを実現する軽量ライブラリです。ReactもVueもビルドツールも設定ファイルも不要で、CDN経由で即座に使い始めることができます。

主な特徴

  • CDN1行で動作:npm installもvite.config.jsも不要
  • ビルドツール不要:HTMLファイルをそのままブラウザで開くだけで動く
  • data-wcs属性でDOM連結:状態とUIを疎結合に保つ設計
  • ES Proxyによる変更検知:パス単位で状態を監視し、該当DOMのみを直接更新
  • 仮想DOMなし:diff計算を行わないため高速かつシンプル
  • 外部依存ゼロ:単体で完結する

内部の仕組み

【内部の仕組み】
ES Proxy で状態オブジェクトを監視
→ data-wcs が設定された DOM 要素のみを直接更新
→ 仮想 DOM の diff 計算なし → 高速かつシンプル

セットアップ方法|CDN1行を追加するだけ

結論:<script type="module">を1行追加するだけで使い始められます。npmもWebpackもViteも一切不要です。

<!-- index.html に1行追加するだけ -->
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>

<!-- これだけで @wcstack/state が使えるようになる -->
<!-- npm install も vite.config.js も不要 -->

基本の書き方|wcs-stateタグとdata-wcs属性

@wcstack/stateの基本パターンは2ステップです。

  1. wcs-stateタグ内に状態(data)とメソッドを定義する
  2. data-wcs属性でDOMと状態のパスを連結する

カウンターの実装例

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <script type="module" src="https://esm.run/@wcstack/state/auto"></script>
</head>
<body>

<!-- ① 状態を wcs-state タグ内に定義 -->
<wcs-state>
  <script type="module">
    export default {
      count: 0,
      increment() { this.count += 1; },
      decrement() { this.count -= 1; }
    };
  </script>
</wcs-state>

<!-- ② data-wcs 属性で状態と DOM を連結 -->
<p data-wcs="textContent: count"></p>
<button data-wcs="onclick: increment">+1</button>
<button data-wcs="onclick: decrement">-1</button>

</body>
</html>

<!-- 動作イメージ:
- count = 0 で画面表示は "0"
- +1 ボタンをクリック → count が 1 になる → 画面が "1" に自動更新 -->

双方向バインディング|input要素との連携

data-wcs="value: 変数名"と指定するだけで、inputへの入力が状態に自動反映され、状態の変化がinputにも自動反映される双方向バインディングが有効になります。

<!-- value にバインドすれば input との双方向が自動で有効になる -->

<wcs-state>
  <script type="module">
    export default {
      name: ""
    };
  </script>
</wcs-state>

<input data-wcs="value: name" placeholder="名前を入力">
<p>こんにちは、{{ name }}さん!</p>

<!-- 動作:
- input に「田中」と入力 → name = "田中" → <p> に「こんにちは、田中さん!」と表示 -->

テンプレート構文{{ }}による埋め込み

<!-- {{ 状態名 }} でテキストを直接埋め込める -->
<p>現在のカウント:{{ count }}</p>
<p>ユーザー名:{{ name }}</p>

<!-- data-wcs="textContent: 〇〇" と同等だが、
     テキストの一部に埋め込む場合はこちらが便利 -->

リスト表示(for)|templateタグで繰り返し

<template data-wcs="for: 配列名">を使うと、配列の要素数だけDOMを自動生成します。*(アスタリスク)が「現在のループ要素」を指すため、手動でインデックスを管理する必要はありません。

<!-- リストの繰り返しは template タグ + for で書く -->

<wcs-state>
  <script type="module">
    export default {
      users: [
        { name: "田中", age: 28 },
        { name: "佐藤", age: 35 },
        { name: "鈴木", age: 22 }
      ]
    };
  </script>
</wcs-state>

<template data-wcs="for: users">
  <div>
    <!-- users.*.name の * が「現在の要素」を指す -->
    <span data-wcs="textContent: users.*.name"></span>
    <!-- 省略記法: .name は users.*.name と同じ -->
    <span data-wcs="textContent: .age"></span>歳
  </div>
</template>

<!-- 出力結果:
田中 28歳
佐藤 35歳
鈴木 22歳 -->

条件分岐(if/elseif/else)|templateタグで表示切り替え

条件が偽のとき、要素はdisplay:noneになるのではなく、DOMから物理的に削除されます。これによりアクセシビリティ的に正しい挙動が保証されます。

<!-- if / elseif / else も template タグで書く -->

<wcs-state>
  <script type="module">
    export default {
      count: 0,
      increment() { this.count += 1; }
    };
  </script>
</wcs-state>

<button data-wcs="onclick: increment">+1</button>
<p>現在のカウント:{{ count }}</p>

<!-- |gt(0) はフィルタ(「0より大きいか?」を判定) -->
<template data-wcs="if: count|gt(10)">
  <p style="color: red;">カウントが10を超えました!</p>
</template>
<template data-wcs="elseif: count|gt(0)">
  <p style="color: green;">カウントは正の値です。</p>
</template>
<template data-wcs="else:">
  <p style="color: gray;">ゼロ以下です。</p>
</template>

<!-- 重要:
- 条件が偽のとき、要素は display:none ではなく DOM から物理的に削除される
- → アクセシビリティ的にも正しい挙動 -->

フィルタ|組み込み40種類の変換・判定関数

フィルタは|フィルタ名の形式で状態パスに連結して使います。条件分岐や表示変換など幅広い用途に対応しています。

カテゴリ フィルタ 説明
比較|gt(n)nより大きいか(greater than)
比較|lt(n)nより小さいか(less than)
比較|eq(n)nと等しいか
比較|gte(n)n以上
比較|lte(n)n以下
文字列|uppercase大文字に変換
文字列|lowercase小文字に変換
文字列|trim前後の空白を削除
数値|toFixed(2)小数点2桁に丸める
その他|not否定(true→false)
その他|length配列/文字列の長さ
その他|isEmpty空かどうか
【使用例】
<template data-wcs="if: users|isEmpty">
  <p>ユーザーが存在しません。</p>
</template>

<span data-wcs="textContent: price|toFixed(2)"></span>

Alpine.js・React・Vueとの比較

@wcstack/stateの位置づけを理解するために、代表的なライブラリ・フレームワークと比較します。

特徴 @wcstack/state Alpine.js React Vue
CDN1行で動作
ビルドツール不要通常必要通常必要
仮想DOM❌(Direct DOM)
状態の定義場所wcs-stateタグx-dataタグuseStatedata()
バンドルサイズ超小型小型中〜大中型
JSX/SFCJSXSFC
型サポート限定的限定的強力強力

Alpine.jsとの設計上の違い

Alpine.jsは既存のDOM要素に状態を直接埋め込む設計(x-data/x-bind)です。一方、@wcstack/stateはwcs-stateタグで状態を独立させ、data-wcsでパスのみを連結します。状態とUIがお互いの実装を知らない疎結合な設計が特徴です。

@wcstack/stateが向いているシーン

  • 静的HTMLページに少量のインタラクティブを追加したい
  • WordPressのページに動的要素を埋め込みたい
  • プロトタイプを素早く作りたい
  • ビルド環境なしで動かす必要がある環境

実践例|TODOリストの実装

for・if・双方向バインディングを組み合わせた実践的なTODOリストの例です。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <script type="module" src="https://esm.run/@wcstack/state/auto"></script>
  <style>
    .done { text-decoration: line-through; color: gray; }
  </style>
</head>
<body>

<wcs-state>
  <script type="module">
    export default {
      newTask: "",
      tasks: [],
      addTask() {
        if (this.newTask.trim() === "") return;
        this.tasks = [...this.tasks, { text: this.newTask, done: false }];
        this.newTask = "";
      },
      toggleDone(index) {
        this.tasks[index].done = !this.tasks[index].done;
        // パスに代入することで変更を通知
        this.tasks = [...this.tasks];
      }
    };
  </script>
</wcs-state>

<h1>TODOリスト</h1>

<input data-wcs="value: newTask" placeholder="タスクを入力">
<button data-wcs="onclick: addTask">追加</button>

<template data-wcs="for: tasks">
  <div>
    <input type="checkbox" data-wcs="onclick: toggleDone">
    <span data-wcs="textContent: .text"></span>
  </div>
</template>

<template data-wcs="if: tasks|isEmpty">
  <p>タスクがありません。追加してみましょう!</p>
</template>

</body>
</html>

生徒

これってjQueryとどう違うんですか?

ペン博士

jQueryは「DOMを手動で操作するライブラリ」じゃ。@wcstack/stateは「状態を定義すれば自動でDOMが更新されるリアクティブシステム」じゃ。jQueryでは $('#count').text(count) と手動で書かなければならないが、@wcstack/stateでは data-wcs="textContent: count" を設定するだけで、countが変わるたびに自動で画面が更新されるんじゃ!

生徒

なるほど!「状態管理」というのはReactやVueだけの概念じゃなくて、HTMLでもできるんですね。軽量なプロジェクトで活用してみます!


よくあるエラーとトラブルシューティング

@wcstack/stateの導入でつまずきやすいポイントと対処法をまとめます。

  • 状態が更新されない:data-wcs属性のバインド名と、state定義のキー名が一致しているか確認する
  • スクリプトが動かない:CDNの読み込みが<body>末尾など、対象HTMLより後になっていないか確認する
  • リストが描画されない:templateタグのfor指定と配列名の綴りを見直す
<!-- 状態の初期値を必ず定義する -->
<wcs-state data-count="0">
  <button data-wcs-click="count++">+1</button>
  <span data-wcs-text="count"></span>
</wcs-state>

エラー時はブラウザの開発者ツール(コンソール)を開き、属性名のタイプミスがないかをまず疑うのが解決の近道です。

よくある質問(FAQ)

本番環境での利用は大丈夫ですか?

比較的新しいライブラリのため、小規模プロジェクト・静的ページへの動的要素追加・プロトタイプ用途には十分適しています。大規模プロダクションやチーム開発では、React/Vue/Svelteなど成熟したエコシステムを持つフレームワークを選択する方が安全です。

TypeScriptは使えますか?

@wcstack/stateは純粋なHTMLとJavaScriptで動作するため、TypeScriptのトランスパイルが必要な場合はビルド環境が必要になります。型安全性を重視する場合は、TypeScriptサポートが充実したReact/Vue/Svelteを選択することをお勧めします。

WordPressで使えますか?

はい。WordPressのテーマやページにCDN読み込みのscriptタグを追加するだけで使えます。問い合わせフォームのバリデーション表示や動的なコンテンツ切り替えなどに活用できます。wp_enqueue_scriptsでCDN URLを読み込むのが正規の方法です。

状態を複数のwcs-stateタグに分割できますか?

ページ内に複数のwcs-stateタグを配置することで、コンポーネントごとに状態を分割して管理できます。各wcs-stateの状態はスコープが独立しているため、名前の衝突を気にせず設計できます。

配列の要素を更新しても画面が更新されない場合は?

ES Proxyはネストされたオブジェクトのプロパティ変更を直接検知できないケースがあります。配列を操作した後に this.tasks = [...this.tasks] のように配列を再代入することで、変更を確実に通知できます。TODOリストの実装例のtoggleDoneメソッドがこのパターンを示しています。


まとめ

  • @wcstack/stateはCDN1行で動作するHTML向けリアクティブ状態管理ライブラリ。ビルドツール・フレームワーク不要。
  • 基本構造wcs-stateタグで状態を定義 → data-wcs属性でDOMと連結 → 状態変更でDOM自動更新。
  • 双方向バインディングdata-wcs="value: 変数名"でinput要素と状態を双方向に連結。
  • リスト表示<template data-wcs="for: 配列名">で繰り返し。*がループの現在要素を指す。
  • 条件分岐if/elseif/elseで要素をDOMから物理的に追加・削除して表示を制御。
  • フィルタ|gt(n)|isEmptyなど40種類の組み込みフィルタで比較・変換が可能。
  • 向いているシーン:静的HTML・WordPress・プロトタイプ・ビルドレス環境への軽量なインタラクティブ追加。

ReactやVueが不要なシンプルなプロジェクトで「少しだけ動的な動作を追加したい」という場面で、@wcstack/stateは非常に有力な選択肢です。まずCDN1行追加してカウンターを動かすところから試してみましょう。


関連記事


参考リンク(公式・一次情報)


AIスキルで、未来の自分をアップデート!

今なら完全無料でAIを学べる!WithAI

今なら完全無料でAIを学べる!

  • 動画や実践で楽しく学べる:初心者でも安心のカリキュラム
  • スマホ・PCどちらでもOK:好きな時間に学習できる
  • 料金は一切ナシ0円でAIスキルが身につく

目的に合わせて選べる「AI副業」「AI転職」「AI活用」の3コースを用意。副収入・キャリアチェンジ・日常の生産性アップまで、あなたのゴールに合わせてAIを学べます。

会員登録はカンタン30秒で完了します。まずは公式LINEから、無料でAI学習をスタートしましょう!

この記事を書いた人

WithCode(ウィズコード)は「目指すなら稼げる人材」をビジョンに、累計400名以上のフリーランスを輩出してきた超実践型プログラミングスクールです。150社以上の実案件支援を特徴にWeb制作・Webデザインなどの役立つ情報を現場のノウハウに基づいて発信していきます。

– service –WithGroupの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次