SPAなビンゴゲームをVue2からVue3に移行した際に行った4つの事と、負債の返済


どんなアプリ?

イベントでチョット使えるSPA(Single Page Application)なビンゴゲーム「Bingo SPA」です。

ビンゴマシンとビンゴカードがワンセットになっています。
ビンゴマシンはこんな感じで動きます。

カードはこのようなものです。

ビンゴマシンとカードは連動していません。連動していません!(大切な事だから2回)
そのため、カードは手元に紙で用意して、ビンゴマシンだけ使う、もしくはその逆も可能となっています。

※カードに至っては、ビンゴ判定すらありません。誰かいい感じの実装をお願いします!

ちなみに SORACOM UG #8 で使いました。あまりにも「あたらない」とネタになっていましたが。
https://uchimanajet7.hatenablog.com/entry/2017/12/16/144824

Vue2 → Vue3 移行で行った事

私のVueアプリケーション作成は、<script>を読み込むケースです。npmではありません。

その上で、Vue2からVue3への移行で行った事は4つです。
全貌はGitHubのdiffをご覧ください。

  1. <script> の読み込み先を変更
  2. new Vue() から Vue.createApp() へ変更
  3. data をオブジェクトから関数へ変更
  4. el を削除して mount() へ変更

ともかくVue3のアプリが起動できてしまえば、問題がある部分はエラーが発生するので、あとは潰していけば良いでしょう。ともかく起動できるところまでが移行の第1ステップです。

以下、diffです。

<script>の読み込み先変更

-  <script src="//jp.vuejs.org/js/vue.min.js"></script>
+  <script src="//unpkg.com/vue@next"></script>

Vue.createApp() への変更、 data の関数化、 el の削除。

-  const app1 = new Vue({
-    data: {
-      options: [],
-      latest: null,
-      results: [],
-      shuffling: false
-    },
+  const app1 = Vue.createApp({
+    data() {
+      return {
+        options: [],
+        latest: null,
+        results: [],
+        shuffling: false
+      }
+    },

mount() への変更

  window.onload = function () {
+   app1.mount('#app1');
  }

これ以降の調整

エラーや意図としない挙動に関しては、Vue2からのマイグレーションガイドを見ましょう。

負債の返済

このビンゴゲームには遊んでいる最中のリロード対策として、番号確定直後やカードをタップした毎に、 sessionStorage() をへ状態を保存しています。

リロードの際には状態を復帰する必要があるわけですが、この実装を今まで(Vue2)の時には、Vueインスタンスを作った後に Windows.onload() 操作していました。
この実装はVue3では動きません。

動くけど...
const app1 = new Vue({
  data: {
    card_id: null,
    cards: []
  },
  ...
});
window.onload = function () {
  if (sessionStorage.getItem('card_id') && sessionStorage.getItem('cards')) {
    app1.card_id = sessionStorage.getItem('card_id');
    app1.cards = JSON.parse(sessionStorage.getItem('cards'));
  }
};

本来このような操作は created() もしくは mounted() で実装すべきだったのです。
これはVue2の頃から存在するインスタンスのライフサイクルにおけるフックメソッドで、ほかには mounted()destroyed() と、インスタンスの状態の変更に合わせて発火します。

created()を使った実装
const app1 = new Vue({
  data: {
    card_id: null,
    cards: []
  },
  created: function() {
    if (sessionStorage.getItem('card_id') && sessionStorage.getItem('cards')) {
      this.card_id = sessionStorage.getItem('card_id');
      this.cards = JSON.parse(sessionStorage.getItem('cards'));
    }
  },
  ...
});

最初からライフサイクルフックメソッドで実装しておけば、Vue3への移行で困ることは無かったわけです。
これは私が知らなかったというのが原因ですが、ここから得られた知見は「副作用を利用すると、アップグレードに弱くなる」ということです。

Vue2からのマイグレーションガイドには、フレームワークが想定している破壊的変更や注意点が列挙されます。即ち、正しくトラブルが発生するため対処もできます。一方、副作用はフレームワーク側から見れば想定外なのでサポートできませんし、それをサポートしろというのは無理があります。

今回負債が返済でき、良かったです。

まとめ

ソフトウェアは設計思想に合わせて利用すると、アップグレードに強い。

ビンゴゲームはMITですので、お気軽にお使いください。
現場からは以上です!

EoT