見出し画像

Mithrilによるシングルページアプリケーション開発 🚀 コンポーネント編

こんにちは。
manebi開発クラ部の中の人、フロントエンド担当のKです。
前回に引き続きMithrilによるシングルページアプリケーション開発の記事になります。

コンポーネントの挙動をカスタマイズする

コンポーネントを作成する中で、コンポーネントが作成されたとき、削除されたときといった、タイミングによる挙動を制御をしたいケースがあります。
代表例としては、データ表示のコンポーネントにおいて、「コンポーネントが作成されたときにデータ取得APIを呼ぶ」といったケースです。
これらはコンポーネントにライフサイクルメソッドを実装することで実現可能です。

oninitメソッド

ライフサイクルには様々なタイミングがありますが、まずは使用頻度が高いoninitを説明します。
oninitは「on initialize」の略で、コンポーネントが初期化されたときに呼ばれます。
前回作成したカウンターコンポーネントにoninitメソッドを実装し、コンソールにメッセージを表示するように変更します。
まずはカウンターコンポーネントをたくさんを呼んでいるmain.jsを元に戻します。

import m from 'mithril'
import Counter from './components/Counter'

class Home {
  view () {
    return m('main', [
      m('h1', 'Mithril SPA'),
      m(Counter)
    ])
  }
}

const element = document.getElementById('app')

m.mount(element, Home)

次にcomponents/Counter.jsを以下のように変更します。

  import m from 'mithril'

  export default class Counter {
    count = 0

    oninit () {
      console.log('Counterが初期化されました。')
    }

    view () {
      const countUp = () => {
        this.count += 1
      }

      return m('div', [
        m('h2', 'カウンター'),
        m('h3', this.count),
        m('button', { onclick: countUp }, 'カウントアップ')
      ])
    }
  }

ブラウザで右クリック→検証をクリックし開発者ツールを開いてください。開発者ツールのコンソールタブに「Counterが初期化されました。」と表示されているはずです。
oninitメソッドは初期化時以外は呼ばれないので、カウントアップを押下して状態を変更しても、コンソールには追加で表示されないことも確認しておきましょう。

コンポーネントに任意の値を渡す

Counterコンポーネントはcountを状態として持っていますが、初期値を外部から設定するケースを考えてみます。
Mithrilのコンポーネントはライフサイクルメソッドとviewメソッドの引数にVirtual Node(以後vnodeと呼称)オブジェクトを受け取ります。vnodeオブジェクトに関してここでは深く触れませんが、attrs(attributesの略)というプロパティが定義されており、attrsプロパティ経由で外部から渡された値を取得できます。
components/Counter.jsを以下のように変更します。

  import m from 'mithril'

  export default class Counter {
    count

    oninit (vnode) {
      // attrsにinitialCountが定義されていればその値を、定義されていなければ0を設定。
      this.count = vnode.attrs.initialCount ?? 0
    }

    view () {
      const countUp = () => {
        this.count += 1
      }

      return m('div', [
        m('h2', 'カウンター'),
        m('h3', this.count),
        m('button', { onclick: countUp }, 'カウントアップ')
      ])
    }
  }

この状態で再度ブラウザにアクセスしても、何も表示が変わっていないはずです。なぜならこのコンポーネントを呼んでいるmain.jsの方で値を設定していないので、初期値である0が表示されているからですね。
main.jsを変更し、カウンターコンポーネントへinitialCountを渡してみます。

import m from 'mithril'
import Counter from './components/Counter'

class Home {
  view () {
    return m('main', [
      m('h1', 'Mithril SPA'),
      m(Counter, { initialCount: 10 })
    ])
  }
}

const element = document.getElementById('app')

m.mount(element, Home)

ブラウザを確認すると初期値として10が表示されているはずです。
余力があればmain.jsで様々なinitialCountと共にCounterコンポーネントを呼び出してみると良いでしょう。
それぞれ別の初期値を持ちながら、独立して動作する様子が確認できます。

まとめ

今回はコンポーネントの基本を解説してみました。
次回はもう少しだけMithrilの核心にせまり、「なぜカウントアップボタンを押すとcountの状態が画面に反映されるか」について解説します。
例によってゆるーく連載していきますので、気長にお待ち下さい🙇‍♂️


この記事が気に入ったらサポートをしてみませんか?