domsubi

A Virtual-DOM Library for JavaScript

Usage no npm install needed!

<script type="module">
  import domsubi from 'https://cdn.skypack.dev/domsubi';
</script>

README

npm version Downloads

domsubi

ブラウザ側のDOM更新をFRPで処理するためのライブラリ。前提としてsodium-typescriptを利用する。

ヴァーチャルDOM実装でもあるが、facebook-reactのJSXとは異なるjavascriptのオブジェクトリテラルを活かした記法(jshtml記法)を採用。

名称はdomsubi = DOM-MUSUBI、DOMのおむすび。sodium(塩)を核にしてDOMを管理するところから。

インストール

umd(依存ライブラリを含めたバンドル版)

domsubiがグローバル変数になる。

<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/domsubi/dist/domsubi.umd.js"></script>

esm(依存ライブラリを含めたバンドル版)

<script type="module" src="https://cdn.jsdelivr.net/npm/domsubi/dist/domsubi.min.js"></script>

esm(別途sodiumjsのモジュール版のインポートが必要)

<script type="module" src="https://cdn.jsdelivr.net/npm/domsubi/dist/domsubi.esm.js"></script>

npm

gt; npm install domsubi
gt; npm install -g domsubi

使用例

domsubi example pageにて紹介。

jshtml記法について

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>

FRP値からノードを生成する

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値を生成する

ヘルパー関数群を用いて生成済みのノードからFRP値を取得できる。

events - DOMイベントをStream化する

const sKeydown = events(document).keydown; // Stream<KeyboardEvent>
sKeydown.listen((e) => console.log(e)); // KeyboardEvent

mutations - DOMの変異をStream化する

const sMutateChild = mutations(document.body, { childList: true }); // Stream<MutationRecord>
sMutateChild.listen((r) => console.log(r)); // MutationRecord

attributes - 属性値のCellを取得する

const attrCell = attributes(document.body).id; // Cell<string>
document.body.setAttribute('id', 'sample-doc');
attrCell.sample(); // "sample-doc"