LoginSignup
8
10

More than 5 years have passed since last update.

Picodom触ってみた

Last updated at Posted at 2017-06-09

Picodomとは

picodom/picodom

vdomでページを操作できるたった1kbのjsライブラリです。メソッドもvdomを組み立てるh、差分反映のpatchの2つしかありません。

Hello Picodom

以下はjsFiddleから実際に動作確認できます。
(jsFiffleなので直接読み込んでますが、pkgで入れる場合はimportにするなりしてください)

hello-picodom.js
/** @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で作った新しいvdompatchへ渡して差分だけ更新してもらう感じです。
多分これより少し複雑な処理だとしても、この状態が基本みたいな感じになるのかなと思います。

FizzBuzzCounter

classで書いたらどんな感じになるだろと思ったので、FizzBuzz言うカウンターを作ってみました。こちらもjsFiddleで動作確認できます。

fizz-buzz-counter.js
/** @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管理ライブラリとの相性辺りもついでに試してみたいと思います。

関連

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10