Picodomとは
vdomでページを操作できるたった1kbのjsライブラリです。メソッドもvdomを組み立てるh
、差分反映のpatch
の2つしかありません。
Hello Picodom
以下はjsFiddleから実際に動作確認できます。
(jsFiffleなので直接読み込んでますが、pkgで入れる場合はimport
にするなりしてください)
/** @jsx h */
const {h, patch} = picodom;
let element = null;
let oldNode = null;
function render(newNode) {
element = patch(
document.body,
element,
oldNode,
newNode
);
oldNode = newNode;
}
function view(state) {
return (
<div>
<h1>{state}</h1>
<input
oninput={e => render(view(e.target.value))}
value={state}
type="text"
/>
</div>
)
}
render(view("Hello Picodom!"))
view
で作った新しいvdom
をpatch
へ渡して差分だけ更新してもらう感じです。
多分これより少し複雑な処理だとしても、この状態が基本みたいな感じになるのかなと思います。
FizzBuzzCounter
class
で書いたらどんな感じになるだろと思ったので、FizzBuzz
言うカウンターを作ってみました。こちらもjsFiddleで動作確認できます。
/** @jsx h */
const {h, patch} = picodom;
class FizzBuzzCounter {
constructor(state) {
this.state = state;
this._element = null;
this._oldNode = null;
}
_increase() {
return () => {
const newState = Object.assign({}, {
count: this.state.count + 1
})
this._update(newState);
}
}
_decrease() {
return () => {
if (this.state.count === 1) {
return;
}
const newState = Object.assign({}, {
count: this.state.count - 1
})
this._update(newState);
}
}
_update(newState) {
this.state = newState;
this.render();
}
_createView() {
const result = (count => {
if (count % 3 === 0 && count % 5 === 0) {
return 'FizzBuzz';
} else if (count % 3 === 0) {
return 'Fizz';
} else if (count % 5 === 0) {
return 'Buzz';
}
return count;
})(this.state.count);
return (
<div class="counter">
<div class="buttons">
<button onclick={this._increase()}>+</button>
<button
class={this.state.count === 1 && 'disabled'}
onclick={this._decrease()}>-</button>
</div>
<div class="result">{this.state.count} : <span style={{color: 'orange'}}>{result}</span></div>
</div>
)
}
render() {
const newNode = this._createView();
this._element = patch(
document.body,
this._element,
this._oldNode,
newNode
);
this._oldNode = newNode;
}
}
const fizzBuzzCounter = new FizzBuzzCounter({count: 1});
fizzBuzzCounter.render();
内容はHelloPicodomのものと対して変わってないです。<button/>
のイベントが起きると、state
を更新して再度render
しています。
jsxの属性値辺りはReactとちょっと違うしWarningみたいなものも無いので、ちょっっとはまりました。例えば、ページの一部分やrollup
と一緒に使って、何かコンポーネントなパッケージを作りたい時にサイズも小さいのでいいんじゃないかと思います。
もうしばらく、state管理ライブラリとの相性辺りもついでに試してみたいと思います。