ブラウザ側のDOM更新をFRPで処理するためのライブラリ。前提としてsodium-typescriptを利用する。
ヴァーチャルDOM実装でもあるが、facebook-reactのJSXとは異なるjavascriptのオブジェクトリテラルを活かしたjshtml記法を採用。
名称はdomsubi = DOM-MUSUBI、DOMのおむすび。sodium(塩)を核にしてDOMを管理するところから。
domsubi
がグローバル変数になる。
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/domsubi/dist/domsubi.umd.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/domsubi/dist/domsubi.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/domsubi/dist/domsubi.esm.js"></script>
$> npm install domsubi
$> npm install -g domsubi
domsubi example pageにて紹介。
jshtml記法ではJavaScriptオブジェクトリテラルでDOMを記述する。入れ子構造をシンプルに扱えるので、FRP値をDOMに手軽に埋め込むことができる。原案となった制作者のページは既にないが、取り扱いの容易さから採用している。
要素は{ タグ: 内容 }
とすることで記述できる。属性を含む場合は、$をキーとして記述する。
{ p: 'Hello World', $: { title: 'Goodbye World' } }
// => <p title="Goodbye World">Hello World</p>
属性値としてイベントハンドラが想定される個所では、Function,EventListenerObjectを指定できる。
{ p: 'Hello World',
$: {
title: 'Goodbye World',
onclick: (e) => console.log(e), // OK
ondblclick: { handleEvent(e) { console.log(e) } } // OK
}
}
style属性はCSSStyleDeclarationにならい、名前付きプロパティをObjectで表現することができる。
{ p: 'Hello World',
$: {
style: {
backgroundColor: 'white',
// "background-color": 'white' でも可
}
}
}
// => <p style="background-color: white;">Hello World</p>
data-*属性については、datasetプロパティのObjectで表現できる。
{ p: 'Hello World',
$: {
dataset: {
exampleMessage: 'Goodbye World' // data-example-message属性になる
}
}
}
// => <p data-example-message="Goodbye World">Hello World</p>
複数のノードを持つ場合はArrayを使えばよい。
{ p: [{ em:'H' },'ello World'] }
// <p><em>H</em>ello World</p>
jshtml記法の中で、DOMにFRPを取り込む時はsodium/Cellを用いればよい。
const message = new CellSink('Hello');
const paragraph = new jshtml({ p: [message,' World'] })
paragraph.mountAsContents(document.body);
message.send('Goodbye'); // <p>Hello World</p> => <p>Goodbye World</p>
ノードの他、属性リスト、属性値にもFRP値を指定できる。
const attr_title_value = new CellSink('Hello');
const attr_values = new Cell({ title: attr_title_value });
const paragraph = new jshtml({ p: 'World', $: attr_values })
paragraph.mountAsContents(document.body);
attr_title_value.send('Goodbye'); // <p title="Hello">World</p> => <p title="Goodbye">World</p>
イベントはsodium/StreamSinkによってStreamとして取得できる。
const sMouseout = new StreamSink();
const paragraph = new jshtml({ p: 'Hello World', $: { onmouseout: sMouseout } })
paragraph.mountAsContents(document.body);
sMouseout.listen((e) => console.log('mouseout from paragraph'));
ヘルパー関数群を用いて生成済みのノードからFRP値を取得できる。
const sKeydown = events(document).keydown; // Stream<KeyboardEvent>
sKeydown.listen((e) => console.log(e)); // KeyboardEvent
const sMutateChild = mutations(document.body, { childList: true }); // Stream<MutationRecord>
sMutateChild.listen((r) => console.log(r)); // MutationRecord
const attrCell = attributes(document.body).id; // Cell<string>
document.body.setAttribute('id', 'sample-doc');
attrCell.sample(); // "sample-doc"