VanJS 試してみた
VanJS?
VanJS is an ultra-lightweight, zero-dependency, and unopinionated Reactive UI framework based on pure vanilla JavaScript and DOM. Programming with VanJS feels like building React apps in a scripting language, without JSX.
VanJS は、純粋な Vanilla JavaScript と DOM に基づいた、超軽量、依存関係なし、固定観念のない Reactive UI フレームワークです。 VanJS を使用したプログラミングは、JSX を使用せずにスクリプト言語で React アプリを構築するような感じです。
ということで、猫も杓子も Node.js なこの時代にあえて「超軽量、依存関係なし、純粋な Vanilla JavaScript」で構築した UI フレームワーク とのことです。
公式のサンプルコードを拝見するとなかなか興味深い内容になっていまして、
// Reusable components can be just pure vanilla JavaScript functions.
// Here we capitalize the first letter to follow React conventions.
const Hello = () => div(
p("👋Hello"),
ul(
li("🗺️World"),
li(a({href: "https://vanjs.org/"}, "🍦VanJS")),
),
)
van.add(document.body, Hello())
// Alternatively, you can write:
// document.body.appendChild(Hello())
これは・・・タグのようでタグじゃない・・・タグと同じ名前の、全部関数??
というわけで、気になったので早速試してみます!
やってみた
VanJS の利用には Node.js が不要で、公式の Getting Started によりますと latest version の VanJS をダウンロードして普通にインポートしなさいと書かれてあります。
今回のお試しでは、以下のようなファイル構成を作ってみました。
├── app.html
└── script
├── main.js
└── van-0.12.0.min.js
サンプル実装
公式のこちらを参考に、シンプルなサンプルを作って動かしてみました。
import van from "./van-0.12.0.min.js"
const { span, button } = van.tags
const Counter = () => {
const counter = van.state(0)
return span(
"❤️ ", counter, " ",
button({onclick: () => ++counter.val}, "👍"),
button({onclick: () => --counter.val}, "👎"),
)
}
export const addCounter = (id) => {
const target = document.querySelector("#"+id)
van.add(target, Counter())
}
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<script type="module">
import { addCounter } from "./script/main.js"
addCounter("web")
</script>
</head>
<body>
<main id="web"></main>
</body>
</html>
結果
「👍」をクリックするとカウンターがインクリメントされ、「👎」をクリックするとデクリメントされます。DOMを操作していることを意識させず、Reactっぽい宣言型に近い記述で要素の組み立てができている様子がわかります。
また VanJS は標準でstateの仕組みを提供しています。サンプルのようにvan.state(初期値)
で生成したstateの値をイベントハンドラで更新するように書いておくと、イベントの発火に応じて影響する要素を更新してくれます。
ReactでいうuseState
の仕組みに近いですが、軽量なライブラリのインポートだけでイージーにstate管理ができるのはありがたいです。
Svelteコンポーネントに VanJS を組み込んでみる
個人的に Svelte が好きでよく使うので、Svelteのコンポーネントで VanJS を使う方法を考えてみました。
VanJS で組み立てた要素を反映させるには、document オブジェクトを経由して目的の要素にadd
する必要があります。ところがSvelteのコンポーネントは基本的にはサーバーサイドでレンダリングされてしまうので、そのままではdocumentオブジェクトにアクセスできず、ReferenceError: document is not defined
などと悲しいエラーを吐かれることになります。
<script>
import { onMount } from 'svelte';
onMount(async () => {
const module = await import('../script/van-0.12.0.min.js');
const { span, button } = module.default.tags;
const c = () => {
const counter = module.default.state(0);
return span(
'❤️ ',
counter,
' ',
button({ onclick: () => ++counter.val }, '👍'),
button({ onclick: () => --counter.val }, '👎')
);
};
const target = document.querySelector('#target');
module.default.add(target, c());
});
</script>
<div id="target" />
一連の処理をonMount
でくくってあげます。onMount
でくくられた処理はコンポーネントのレンダリング後に、クライアントサイドで実行されるので、document
にも問題なくアクセスできます。
まとめ
以上です。
VanJSは「超軽量、依存関係なし、純粋な Vanilla JavaScript」を謳う、既存のフレームワークに対するアンチテーゼ的な思いを感じるライブラリでした。
その性質上、ReactやSvelteなど既存のJavaScriptライブラリと併用するには少しコツが要りそうですが、ちょっとした動的なコンポーネントを作りたいような場合で便利な使い方ができそうですし、state
の仕組みがあるのでなんならこれひとつでSPAを作ったりもできちゃうのでは・・・?と夢がふくらみます。
ぜひ、ご参考いただければ幸いです。
ではまた!
Discussion