幾つかの原因が重なって期待する動作にならないようです。
既存scriptのコードの修正
scriptのコードの下記2カ所の修正が必要です。
vue
1<script>
2export default {
3 name: 'Test',
4 data() {
5 return {
6 // (1) dataではなく
7 // msg: this.$store.getters.formatGlobalDate
8 }
9 },
10 computed: {
11 // (1) computedに記述する必要がある
12 msg() {
13 return this.$store.getters.formatGlobalDate;
14 }
15 },
16 methods: {
17 incMonth() {
18 // (2) dispatchではなくcommitとする必要がある
19 // this.$store.dispatch('incMonth');
20 this.$store.commit('incMonth')
21 }
22 }
23}
24</script>
ただし、この修正だけではデータの変更はページに反映されません。
Dateの変更を検知させる修正
ここからは私も初めて知ったのですが、まず、Date型のプロパティはそのままではリアクティブにならないようです。
また、VuexだからではなくVue.js自体がそのような挙動で、下記のStackOverFlowに似たような質問が投稿されています。
この質問の回答によればDateインスタンスを再生成すれば変更が検知されるということなので、VuexのincMonth
メソッドを下記のように修正してみます。
この修正を行ったあとに動作確認すると変更がページに反映されると思います。
javascript
1mutations: {
2 incMonth(state) {
3 state.CurrentMonth.setDate(1)
4 state.CurrentMonth.setMonth(state.CurrentMonth.getMonth() + 1)
5 // 追加
6 state.CurrentMonth = new Date(state.CurrentMonth)
7 }
8}
さらにVuexの問題でないことを確認するために、Vuexを使わない下記のコンポーネントで動作確認してみます。
クリックするたびにmsgは更新されますがページには反映されないと思います。
vue
1<template>
2 <div class="content">
3 <h1>{{ msg }}</h1>
4 <a class="button" @click="incMonth">加算</a>
5 </div>
6</template>
7
8<script>
9export default {
10 name: 'Test',
11 data() {
12 return {
13 msg: new Date()
14 }
15 },
16 methods: {
17 incMonth() {
18 this.msg.setDate(1)
19 this.msg.setMonth(this.msg.getMonth() + 1)
20 // この行を有効にすると反映される
21 //this.msg = new Date(this.msg)
22 }
23 }
24}
25</script>
Dateはリアクティブにならないのか
上記の確認から『Dateインスタンスの状態変更はリアクティブにならず、Dateインスタンスの再生成はリアクティブになる』ように思うのですが、どうしてインスタンスの状態変更がリアクティブにならないのかは私もわかりません。
リアクティブの探求というページでは
Vue の最大の特徴の1つは、控えめなリアクティブシステムです。モデルは単なるプレーンな JavaScript オブジェクトです。
という記述が冒頭にあります。
この”単なるプレーンなJavaScript オブジェクト”(just plain JavaScript objects)とは何を指しているのか、Date型のインスタンスはプレーンなJavaScript オブジェクトではないのか、などオフィシャルのドキュメントではよくわかりませんでした。
また、JavaScriptにはPOJO (plain old javascript objects)という言葉があり、これがVue.jsの言う”単なるプレーンなJavaScript オブジェクト”と同じ意味なのかも不明です。
追記 (2020/08/11)
だいぶ昔ですが、似た現象での質問がありました。
こちらの回答によれば
There are some caveats on reactivity of vue and as Object.observe is obsolete now, it can not track if an javascript object has changed internally, unless you clone the object and create a new object which is needed in your case.
vueのreactivityにはいくつかの注意点があります。Object.observeは現在廃止されているため、オブジェクトのクローンを作成して必要な新しいオブジェクトを作成しない限り、JavaScriptオブジェクトが内部で変更されたかどうかを追跡できません。
とのことです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/10 19:55