質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

Q&A

解決済

1回答

2631閲覧

Vuexで、stateの変更が他のコンポーネントで検知できない

belgh

総合スコア27

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vuex

Vuexは、Vue.js アプリケーションのための状態管理ライブラリです。アプリケーション内で使用するコンポーネントのための集中データストアを提供。コンポーネント同士でデータをやり取りし、処理のフローを一貫させたり、データの見通しを良くすることができます。

2グッド

1クリップ

投稿2020/08/09 08:44

表題通りの件で、公式を見ても理解できず悩んでおり、質問させていただきます。

store/index.js

js

1export default new Vuex.Store({ 2 state: { 3 CurrentMonth: new Date() 4 }, 5 getters: { 6 formatGlobalDate: state => { 7 return state.CurrentMonth.toLocaleDateString('ja-JP') 8 } 9 }, 10 mutations: { 11 incMonth (state) { 12 state.CurrentMonth.setDate(1); 13 state.CurrentMonth.setMonth(state.CurrentMonth.getMonth() + 1); 14 }
components/Test.vue

js

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: this.$store.getters.formatGlobalDate 14 } 15 }, 16 methods: { 17 incMonth () { 18 this.$store.dispatch('incMonth'); 19 // this.msg = this.$store.getters.formatGlobalDate; 20 } 21 } 22</script>

getterやcomputedを使っても、CurrentMonthの更新を検知(msgに反映)することが出来ません。
何が悪いのでしょうか。
ご教示お願いいたしますm(_ _)m

Maruco2321, nemumi-nomaki👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

幾つかの原因が重なって期待する動作にならないようです。

既存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 14:37

編集2020/08/10 16:05
rubytomato

総合スコア1752

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

belgh

2020/08/10 19:55

ありがとうございます! コードの誤りはもとより、「オブジェクトは再生成しなければ変更が検知されることはない」とのこと、勉強になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問