



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









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



それを実現するのが @wcstack/state じゃ!CDNを1行読み込むだけで、ビルドツールもnpm installも不要でリアクティブなHTMLが書けるんじゃ。data-wcs属性で状態とDOMを繋ぐだけで、カウンター・双方向バインディング・リスト表示・条件分岐まで実装できるぞ!
@wcstack/state の概要と内部の仕組み(ES Proxy・Direct DOM更新)wcs-stateタグ・data-wcs属性)@wcstack/stateは、HTMLファイル1つで「値が変わったらDOMが自動で更新される」リアクティブな仕組みを実現する軽量ライブラリです。ReactもVueもビルドツールも設定ファイルも不要で、CDN経由で即座に使い始めることができます。
data-wcs属性でDOM連結:状態とUIを疎結合に保つ設計【内部の仕組み】
ES Proxy で状態オブジェクトを監視
→ data-wcs が設定された DOM 要素のみを直接更新
→ 仮想 DOM の diff 計算なし → 高速かつシンプル結論:<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 も不要 -->@wcstack/stateの基本パターンは2ステップです。
wcs-stateタグ内に状態(data)とメソッドを定義する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" に自動更新 -->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: 〇〇" と同等だが、
テキストの一部に埋め込む場合はこちらが便利 --><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歳 -->条件が偽のとき、要素は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 から物理的に削除される
- → アクセシビリティ的にも正しい挙動 -->フィルタは|フィルタ名の形式で状態パスに連結して使います。条件分岐や表示変換など幅広い用途に対応しています。
| カテゴリ | フィルタ | 説明 |
|---|---|---|
| 比較 | |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>@wcstack/stateの位置づけを理解するために、代表的なライブラリ・フレームワークと比較します。
| 特徴 | @wcstack/state | Alpine.js | React | Vue |
|---|---|---|---|---|
| CDN1行で動作 | ✅ | ✅ | ❌ | ❌ |
| ビルドツール不要 | ✅ | ✅ | 通常必要 | 通常必要 |
| 仮想DOM | ❌(Direct DOM) | ❌ | ✅ | ✅ |
| 状態の定義場所 | wcs-stateタグ | x-dataタグ | useState | data() |
| バンドルサイズ | 超小型 | 小型 | 中〜大 | 中型 |
| JSX/SFC | ❌ | ❌ | JSX | SFC |
| 型サポート | 限定的 | 限定的 | 強力 | 強力 |
Alpine.jsは既存のDOM要素に状態を直接埋め込む設計(x-data/x-bind)です。一方、@wcstack/stateはwcs-stateタグで状態を独立させ、data-wcsでパスのみを連結します。状態とUIがお互いの実装を知らない疎結合な設計が特徴です。
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定義のキー名が一致しているか確認する<body>末尾など、対象HTMLより後になっていないか確認するtemplateタグのfor指定と配列名の綴りを見直す<!-- 状態の初期値を必ず定義する -->
<wcs-state data-count="0">
<button data-wcs-click="count++">+1</button>
<span data-wcs-text="count"></span>
</wcs-state>エラー時はブラウザの開発者ツール(コンソール)を開き、属性名のタイプミスがないかをまず疑うのが解決の近道です。
比較的新しいライブラリのため、小規模プロジェクト・静的ページへの動的要素追加・プロトタイプ用途には十分適しています。大規模プロダクションやチーム開発では、React/Vue/Svelteなど成熟したエコシステムを持つフレームワークを選択する方が安全です。
@wcstack/stateは純粋なHTMLとJavaScriptで動作するため、TypeScriptのトランスパイルが必要な場合はビルド環境が必要になります。型安全性を重視する場合は、TypeScriptサポートが充実したReact/Vue/Svelteを選択することをお勧めします。
はい。WordPressのテーマやページにCDN読み込みのscriptタグを追加するだけで使えます。問い合わせフォームのバリデーション表示や動的なコンテンツ切り替えなどに活用できます。wp_enqueue_scriptsでCDN URLを読み込むのが正規の方法です。
ページ内に複数のwcs-stateタグを配置することで、コンポーネントごとに状態を分割して管理できます。各wcs-stateの状態はスコープが独立しているため、名前の衝突を気にせず設計できます。
ES Proxyはネストされたオブジェクトのプロパティ変更を直接検知できないケースがあります。配列を操作した後に this.tasks = [...this.tasks] のように配列を再代入することで、変更を確実に通知できます。TODOリストの実装例のtoggleDoneメソッドがこのパターンを示しています。
wcs-stateタグで状態を定義 → data-wcs属性でDOMと連結 → 状態変更でDOM自動更新。data-wcs="value: 変数名"でinput要素と状態を双方向に連結。<template data-wcs="for: 配列名">で繰り返し。*がループの現在要素を指す。if/elseif/elseで要素をDOMから物理的に追加・削除して表示を制御。|gt(n)|isEmptyなど40種類の組み込みフィルタで比較・変換が可能。ReactやVueが不要なシンプルなプロジェクトで「少しだけ動的な動作を追加したい」という場面で、@wcstack/stateは非常に有力な選択肢です。まずCDN1行追加してカウンターを動かすところから試してみましょう。


目的に合わせて選べる「AI副業」「AI転職」「AI活用」の3コースを用意。副収入・キャリアチェンジ・日常の生産性アップまで、あなたのゴールに合わせてAIを学べます。
会員登録はカンタン30秒で完了します。まずは公式LINEから、無料でAI学習をスタートしましょう!
公式サイト より
今すぐ
無料カウンセリング
を予約!