プロジェクトが進んで行くと同じような処理が複数のファイルに出てきて、共通化したくなってきます。(スコープ分けたかったので、今までは親子componentの分割に留めました)
共通化する事で、可読性が上がり保守・改修コストが抑えられたり、潜在的な不具合(バグ)を減らす事ができます。
共通化の方法はいくつかあり、良し悪しがありますので、ケース毎に使い分けるのが良さそう。
今回はmixinとinjectを使い、命名規則も決めて、可読性を意識してリファクタリングしました。

mixinで共通化

mixinは賛否両論あると思いますが、script内をmixin先に委ねられるので便利です。
mixin元では、唐突にimportやdataの変数、methodが出てくるので、敬遠する人もいますが、個人的にはRailsの継承をよく使っていたので、違和感は少なかったです。

ただ、名前の通り、継承ではなくミックスなので、継承元が優先される訳ではなく、両方実行されます。この時、mixin先が先に実行されるのと、await使っている場合だけかもですが、終了を待たずにmixin元やmounted(createdに対して)が実行されるので、mixin先で共通化できない場合もありそうです。

mixin先

目的に応じて分けるのも良いかもですが、複数あると複雑になるので、先ずは1つにしました。
ページにより使っていないcomponentやmethodもありますが、実害がないのでそのままに。

plugins/application.js を作成

import Loading from '~/components/Loading.vue'
import Message from '~/components/Message.vue'

export default {
  components: {
    Loading,
    Message
  },

  data () {
    return {
      loading: true,
      processing: true,
      alert: null,
      notice: null
    }
  },

  methods: {
    appSetQueryMessage () {
      this.alert = this.$route.query.alert
      this.notice = this.$route.query.notice
      this.$router.push({ path: this.$route.path }) // Tips: URLパラメータを消す為
    },
    appRedirectSuccess (alert, notice) {
      this.$toasted.error(alert)
      this.$toasted.info(notice)
      this.$router.push({ path: '/' })
    }
  }
}

mixin元から移しています。
処理はメソッドにして、命名をapp〜とする事で、mixin先のapplication.jsにありそうだなと解るようにと、被らないようにしています。

mixin元

pages/users/sign_in.vue を変更

- import Loading from '~/components/Loading.vue'
- import Message from '~/components/Message.vue'
+ import Application from '~/plugins/application.js'
  components: {
    ValidationObserver,
-    ValidationProvider,
+    ValidationProvider
-    Loading,
-    Message
  },
+  mixins: [Application],

mixin先に移したのを削除して、application.jsをmixin

  data () {
    return {
-      loading: true,
-      processing: true,
-      alert: null,
-      notice: null,
      email: '',
      password: ''
    }

ここもmixin先に移したのを削除

  created () {
<省略>
        if (this.$auth.loggedIn) {
-          this.$toasted.error(this.$route.query.alert)
-          this.$toasted.info(this.$route.query.notice)
-          return this.$router.push({ path: '/' })
+          return this.appRedirectSuccess(this.$route.query.alert, this.$route.query.notice)
        }
-    this.alert = this.$route.query.alert
-    this.notice = this.$route.query.notice
-    this.$router.push({ path: this.$route.path }) // Tips: URLパラメータを消す為
+    this.appSetQueryMessage()

mixin先でメソッド化して移しています。

     this.processing = false
     this.loading = false
  },

本当は、mixin先で共通化したかったのですが、mixin先の方が先に実行されるのと、mixin先のmountedが先に実行されてしまうので、冗長になりますが、mixin元で対応しました。

可読性向上

clickイベントは、on〜とする事にしました。他でも良く見ます。

-            <v-btn color="primary" :disabled="invalid || processing" @click="signIn">
+            <v-btn color="primary" :disabled="invalid || processing" @click="onSignIn()">
   methods: {
-    async signIn () {
+    async onSignIn () {

injectで共通化

computedもmixinで出来ますが、mixinしていないlayouts/default.vueでも使いたかったので、injectにしました。
普通にjsをimportでも良いのですが、ページ毎の手続きが不要で、$〜で呼び出すので、pluginsにありそうだなと解りそう。

nuxt.config.js に追加

  plugins: [
    { src: '~/plugins/axios.js' },
+    { src: '~/plugins/utils.js' }
  ],

plugins/utils.js を作成

const dateFormat = (date, locales) => {
  if (date == null) { return }

  const dtf = new Intl.DateTimeFormat(locales, { year: 'numeric', month: '2-digit', day: '2-digit' })
  return dtf.format(new Date(date))
}

export default (_context, inject) => {
  inject('dateFormat', dateFormat)
}

layouts/default.vue を変更

-          このアカウントは{{ dateFormat($auth.user.destroy_schedule_at) }}以降に削除されます。
+          このアカウントは{{ $dateFormat($auth.user.destroy_schedule_at, 'ja') }}以降に削除されます。
  computed: {
    displayItems () {
      return this.items.filter(item => (item.loggedIn === null) || (item.loggedIn === this.$auth.loggedIn))
-    },
-    dateFormat () {
-      return function (date) {
-        const dtf = new Intl.DateTimeFormat('ja', { year: 'numeric', month: '2-digit', day: '2-digit' })
-        return dtf.format(new Date(date))
-      }
    }
  }

今回のコミット内容
https://dev.azure.com/nightonly/nuxt-app-origin/_git/nuxt-app-origin/commit/3ce2aa4f8b98a9337381e6102f7fed35b9d75b15

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です