Zenn Dev Ryo Kawamata Articles 1ad6e51eed13ae
VanJS で素のDOM操作をリファクタしてみた
- URL: https://zenn.dev/ryo_kawamata/articles/1ad6e51eed13ae
- 日付: 2026-06-26
- Tier: Tier 3
- 要旨: Chrome拡張Sky Follower Bridgeのcontent scriptにおける素のDOM操作をVanJSでリファクタリングした事例。VanJSはgzip後0.9kbと超軽量でトランスパイル不要のReactive UIフレームワークであり、Chrome拡張のcontent scriptのようにReactやVueのフルフレームワークを持ち込みにくい文脈で有効な選択肢となる。リファクタリング前はinsertAdjacentHTMLとaddEventListenerのクラス付け変えによるイベント管理で可読性が低かったが、VanJSのvan.state/van.deriveによる状態管理とコンポーネント分割により、UIとイベントの関連が一目でわかる宣言的なコードになった。
詳細
VanJSの特徴
- gzip圧縮後0.9kb、依存なし、トランスパイル不要
- JSXを使わず関数ベースのAPIで宣言的なUI構築
- van.state()で状態管理、van.derive()で状態から派生値を算出
- van.add(element, component)でDOMにコンポーネントをマウント
リファクタリング前の問題(insertAdjacentHTML + addEventListener)
- HTMLテンプレートリテラルでDOMを構築し、後からaddEventListenerを登録
- ボタンの状態変化はclassList.add/remove/containsとtextContent書き換えで直接操作
- UIとイベントロジックの対応関係が追いにくく可読性が低い
リファクタリング後の構造
- BskyUserCell, ActionButton, Avatar の3コンポーネントに分割
- ActionButtonはvan.state()で label, isStateOfBeing, isProcessing, isJustApplied の4状態を管理
- van.derive()でCSSクラス名を状態から派生(beingClass, processingClass, justAppliedClass)
- マウント処理: van.add(dom.parentElement, BskyUserCell({…})) の1行
適用場面
- Chrome拡張のcontent scriptのような制約のある環境
- 静的サイトにピンポイントでReactiveなUIを追加したいケース