ひびのログ

日々ではないけどログを出力していくブログ

Vue.js 3.0 で追加される Composition API をさっと舐めてみた

まえがき

Vue.js 3.0 も RC まで来ていて、その最も大きい変更である Composition API が 2.x でも使えるので使ってみた。
使い方は巷に溢れているので、使ってみた感想をメインにまとめてみる。

github.com

TL; DR

  • データと処理をまとめられる
  • 自由度が高い
  • 【求】ベストプラクティス

Composition API とは?

2.x までの new Vue(options) という宣言的な書き方(Options API)とは違い、setup という関数の中で手続き的に書ける新記法。 詳しくは Google 先生。

実際に使ってみた

ポートフォリオをサクッと作ってみようかなーと思い、簡単なアプリ的なものを作ってみた。 ユーザー管理アプリとして、ユーザー一覧から追加・編集・削除ができる。

github.com

使ってみた感想

良かったところ

データと処理がひとまとめになる

(言葉の定義があっているかはわからないが)ドメインとコンテキストをまとめておける。
オブジェクト指向的に言えばカプセル化にも近い?

処理を関数として書ける・分割できる、this を使わない

Options API とは違い this を使わないので、純粋な関数として外出しできる。
つまり 1 ファイルにずらずら書くのではなく、必要な単位でまとめて外部化できる。

オブジェクト指向にも関数型にも使える

純粋な関数でも書けるし、クロージャーでも書けるので完全なカプセル化・メッセージングを実現できる。

Composition 同士を合成することができる

関数なので、順番に実行もできるし、Composition 内で Composition を実行できるし、非同期関数なら Promise.All などもできるし、部分適用やコールバックも使える。 ポリモーフィズムもこれで実現できそう。

型推論が効く

Vue.js は TypeScript と相性が悪いと言われて長いが、Composition API は型推論がほとんどの部分で効く。最高。 props に関しても、2.x の書き方で書いても型推論が効く(type: String と書くと string で型がつく)。
ただし、ArrayObject についてはうまいこと書けなかったので、よりいい書き方を調べたい。

Decorator を使わない

vue-property-decorator を使えば、Options API でも Decorator を使って型が付けられるようになる。
しかし、一部プログラマ側で型を担保する必要があったり、そもそも Decorator は experimental な機能で今の ECMAScript の仕様とずれてしまっている部分があったりする。
それを使わずに済むのは、今後のことを考えるととてもありがたい。

これまでと同じ記法が使える

Options API に setup というオプション(と emits)が追加されるだけで、これまでの記法と共存できる。 これにより、progressive にも置き換えていける(はず)。
例えば、Account の Composition を作って置き換え、Article の Composition を作って置き換え、のようにできる(といいなぁ)。

いまいちなところ

翻って、若干使いづらいなーと思った部分を上げていく。

値が書き換え可能な状態で公開される

ref された値は .value すれば代入できてしまうので、let と同じように書き換えを心配する必要がある。
もしかすると computed などを使えばうまいこと読み取り専用で返せるのかもしれないと今思った。

refreactive がある

  • ref がプリミティブ(配列含む)に、reactive はオブジェクトに使う
  • ref された値は .value が必要だが、reactive された値はいらない(e.g. obj.foo
  • const { foo, bar } = reactive(obj) とするとリアクティブにならないので、専用の関数を噛ませる必要がある

と、そこそこ癖がある。
自分としては、関数内では reactive を使っていいが、外部に出すときはすべて ref に変換するようにすれば解決できそうだと感じた。

setup 関数が async function にできない(asyncData 的な)

Nuxt.js ユーザーなのでこれができたらいいなーと思った。
then で待つかライフサイクルフックに渡すコールバックを async function にしてあげることで解決。

context.root が若干面倒

this から一階層増えたなって、それだけ。

Vuex とのからみ

両方データを管理するものなので、どちらをどこまで使うか悩む。

クロージャーにしてしまえば、Composition API でグローバルステートも管理できる。
Composition API に寄せるのがいいのか、はたまたグローバルステートだけ Vuex に入れるのがいいのか。
会員情報登録フローなど、Composition がページを跨ぐときにはどちらを使うのか。

ベストプラクティスが定まっていない(それはそう)

上の流れがあり、まだこういったベストプラクティスが定まっていないというのがなかなか難しいところ。
プロダクトが違ったら書き方も違う、といったことにもなりがち。

VueUse というライブラリがあるので、Composition 分割に関しては参考になりそう。

github.com

まだわかってない(これから調べたい)ところ

  • API でのローディング中の表示
    • Vue.js 3.0 でいい感じの書き方ができるという記事を見た気がするが、詳しくは覚えていない
  • プラグインの書き方
    • Options API でしか書けなかったので、beforeSetup のようなものが書けたら便利かなーと思った。

総括

  • API アクセス→データ設定→View で表示 という流れを作るとき、処理をまとめて書けるのでわかりやすい
    • 以前は、this を使いつつ計算を挟んだりすると、途端に流れがわかりづらくなっていたのでよさげ
  • ドメイン単位で処理をまとめておけるので、処理ごとにファイル分割がやりやすそう
  • Composition 同士を組み合わせたり合成したりすることができるので、可能性が無限大
    • 感覚的に React の HOC と近いイメージなのかな?
  • とはいえ、まだまだ新しい概念なので、これから出てくるベストプラクティスに期待
    • Options API よりいろいろな書き方ができそうなので、標準的な書き方が定まると助かる