【Vue】moment-js
moment-jsとは
こんにちは!大ちゃんの駆け出し技術ブログです。
この記事では日付フォーマットを変換するプラグインのmoment-js
について紹介します。自分のPF作成で使用したため忘れぬうちにアウトプットさせていただきます。
今回自分がこのプラグインを使用した理由は、railsのAPIで渡されるdatetime
の値のフォーマットを変更したいためです。
通常created_at
やupdated_at
などのdatetime
カラムは保存されると以下のようなフォーマットになるかと思います。
"created_at":"2019-04-21T00:00:00.000Z"
自分のPFでは誕生日と入社日というカラムをdatetime
で追加していたため、これをrailsサーバーからJSON形式で値を受け取ると同様のフォーマットで受け取っていました。これをvue.js側で表示すると、表示される画面は以下のようになります。
[該当コード]
<div>{{ profile.birthday }}</div>
[表示画面] (画質が荒く申し訳ございません。)
これを解消する方法としては2つあるかなと思いました。
上記2つの違いはバックエンドがフロントエンドかということだけです。JSONの値のフォーマットを変更するという点では共通なので、処理内容は同じになるかと思います。
まずバックエンド側で整形する方法ですが、これは個人的に思ったのですが好ましくないのかなと思いました。理由としては、本来のサーバー側でレンダリングしているフォーマットはサーバー側で保存しているフォーマットと一致しているのが一般的だと思います。(enumは話が別になりますが、、、)。ですのでサーバー側で表示する誕生日のJSONの値だけフォーマットを部分的に変更するという仕様は違和感がありました。また、フロント側で値を加工することが多いので値自体の加工はフロント側で統一した方がいいのかなとも思いました。
ではフロント側で受け取った値を加工するというのはどうでしょうか。これはvuex
のgetters
のように受け取った値を加工するという仕様があるため問題なさそうです。
computed: { doneTodosCount () { return this.$store.state.todos.filter(todo => todo.done).length } }
しかし、javascriptに慣れていないためか処理が冗長になると感じました。上記の例とは違い、プロフィール群の全てのプロフィールの誕生日の値のフォーマットを変更するという処理はかなり文が長くなることが予想されます。もっと簡単に処理できる方法はないのかと悩んでいました。
そこで今回使用するプラグイン、moment-js
を使用することにしました。導入するとmoment-js
でYYYY年/mm月/dd日というフォーマットに変更することができました。
インストール方法
railsを使用しているのでwebpackerに任せてインストールします。個人的にmoment-js
の他の記事はそのままのvue(vue-clii)での開発のパターンが多くyarnでインストールしている記事は見当たりませんでしたが、問題なく実装できますのでご安心ください。
$ yarn add moment yarn add v1.22.10 [1/4] 🔍 Resolving packages... [2/4] 🚚 Fetching packages... [3/4] 🔗 Linking dependencies... warning " > vue-loader@15.9.6" has unmet peer dependency "css-loader@*". warning " > vue-loader@15.9.6" has unmet peer dependency "webpack@^3.0.0 || ^4.1.0 || ^5.0.0-0". warning " > webpack-dev-server@3.11.2" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0". warning "webpack-dev-server > webpack-dev-middleware@3.7.3" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0". [4/4] 🔨 Building fresh packages... success Saved lockfile. success Saved 1 new dependency. info Direct dependencies └─ moment@2.29.1 info All dependencies └─ moment@2.29.1 ✨ Done in 4.07s.
次にコンポーネント自体にインポートします。誕生日をフォーマットを変更して表示するページが今のところ1ページのみですので、今回はページのコンポーネントに直接インストールしました。
<script> import moment from "moment"; export default { }; </script>
次にexport defaulltの中にfilters
でフォーマットを指定します。
<script> import moment from "moment"; export default { filters: { moment: function(date) { return moment(date).format("YYYY年/MM月/DD日"); }, } }; </script>
filters
に関しては全く知らなかったのですが、どうやらmustache
などで値のフォーマットや大文字小文字を加工する時などに使われているようです。公式にも記載がありました。
format("YYYY年/MM月/DD日")
の部分で好きなフォーマットを指定します。format("YYYY/MM/DD")
といった年などを削除しても可能です。
これで準備は完了です。あとは以下のように変換したい日付 | moment
とmustache
の中に記載します。
[変更前]
<div>誕生日: {{ profile.birthday }}</div>
↓
[変更後]
<div>誕生日: {{ profile.birthday | moment }}</div>
これにより値のフォーマットが意図したものに加工されました。
問題点
今回はあまりフォーマットの実装自体に時間をかけたくなかったのでmoment-jsで実装しましたが、今後こちらの実装で予想される問題点もあります。
例えば、誕生日カラムだけでなく、記念日というカラムを追加しようとした時に、そのページには2箇所のmoment
の記載が必要です。
<div>誕生日: {{ profile.birthday | moment }}</div> <div>誕生日: {{ profile.memorial | moment }}</div>
さらに増えると3箇所というふうにそのページでmoment
を記載しなければならない箇所がどんどん増えていきます。それはかなり冗長に思えますので、それだったらvuexのgettersで一度に加工してしまった方が処理が冗長でも管理が楽なのかもしれません。それについてわかったらこちらの記事に追記したいと思います。
以上、大ちゃんの駆け出し技術ブログでした!