前提・実現したいこと
生年月日をselect
で選択し、選択内容をstore
のstate
に保存し、それを2ページ目で表示したいです。
発生している問題・エラーメッセージ
error Duplicated key 'year' error Duplicated key 'month' error Duplicated key 'day'
該当のソースコード
src/router/index.js
javascript
1import Vue from 'vue' 2import VueRouter from 'vue-router' 3import page1 from '../pages/page1.vue' 4 5Vue.use(VueRouter) 6 7const routes = [ 8 { 9 path: '/', 10 name: 'page1', 11 component: page1 12 }, 13 { 14 path: '/page2', 15 name: 'page2', 16 // route level code-splitting 17 // this generates a separate chunk (about.[hash].js) for this route 18 // which is lazy-loaded when the route is visited. 19 component: () => import(/* webpackChunkName: "about" */ '../pages/page2.vue') 20 } 21] 22 23const router = new VueRouter({ 24 mode: 'history', 25 base: process.env.BASE_URL, 26 routes 27}) 28 29export default router 30
src/store/index.js
javascript
1import Vue from 'vue' 2import Vuex from 'vuex' 3 4Vue.use(Vuex) 5 6export default new Vuex.Store({ 7 state: { 8 year: '', 9 month: '', 10 day: '' 11 }, 12 mutations: { 13 setYear (state, year) { 14 state.year = year 15 }, 16 setMonth (state, month) { 17 state.month = month 18 }, 19 setDay (state, day) { 20 state.day = day 21 } 22 }, 23 actions: { 24 getYear: ({commit}, year) => { 25 commit('setYear', year) 26 }, 27 getMonth: ({commit}, month) => { 28 commit('setMonth', month) 29 }, 30 getDay: ({commit}, day) => { 31 commit('setDay', day) 32 } 33 }, 34 getters: { 35 currentYear: state => { 36 return state.year 37 }, 38 currentMonth: state => { 39 return state.month 40 }, 41 currentDay: state => { 42 return state.day 43 } 44 } 45}) 46
src/pages/page1.vue
javascript
1<template> 2 <div class="page1"> 3 <p>生年月日</p> 4 <form><!--年号も合わせて生年月日を選択します--> 5 <select v-model="year" @change="getDays"> 6 <option v-for="n in 100" v-bind:value="n + 1921" v-bind:key="n">{{(n + 1921) | era}}</option> 7 </select>年 8 <select v-model="month" @change="getDays"> 9 <option v-for="n in 12" v-bind:key="n">{{n}}</option> 10 </select>月 11 <select v-model="day" @change="getDays"> 12 <option v-for="n in daysMax" v-bind:key="n">{{n}}</option> 13 </select>日 14 </form> 15 <router-link to="/page2">次へ進む</router-link> 16 </div> 17</template> 18 19<script> 20export default { 21 data() { 22 return { 23 year: 2000, 24 month: 1, 25 day: 1, 26 daysMax: '' 27 } 28 }, 29 created() { 30 this.getDays() 31 }, 32 computed: { 33 year: { 34 get() { 35 return this.$store.getters.year 36 }, 37 set(value) { 38 this.$store.dispatch("getYear", value) 39 } 40 }, 41 month: { 42 get() { 43 return this.$store.getters.month 44 }, 45 set(value) { 46 this.$store.dispatch("getMonth", value) 47 } 48 }, 49 day: { 50 get() { 51 return this.$store.getters.day 52 }, 53 set(value) { 54 this.$store.dispatch("getDay", value) 55 } 56 }, 57 }, 58 methods: { 59 getDays: function() {//月末の日にちを計算します。例えば、2月であれば28日(うるう年以外)。 60 this.daysMax = new Date(this.year, this.month, 0).getDate(); 61 } 62 }, 63 filters: {//西暦に対する和暦を計算します。 64 era(y) { 65 let result; 66 if (y > 2018) { 67 result = `${y} (令和${y-2018})`; 68 } else if (y > 1988) { 69 result = `${y} (平成${y-1988})`; 70 } else if (y > 1925) { 71 result = `${y} (昭和${y-1925})`; 72 } else if (y > 1911) { 73 result = `${y} (大正${y-1911})`; 74 } 75 return result; 76 } 77 } 78}; 79</script> 80
src/pages/page2.vue
javascript
1<template> 2 <div class="page2"> 3 <p>生年月日</p> 4 <p>{{$store.getters.currentYear}}年{{$store.getters.currentMonth}}月{{$store.getters.currentDay}}日</p> 5 </div> 6 <router-link to="/">前に戻る</router-link> 7 </div> 8</template> 9 10<script> 11export default { 12 computed: { 13 currentYear() { 14 return this.$store.getters.currentYear 15 }, 16 currentMonth() { 17 return this.$store.getters.currentMonth 18 }, 19 currentDay() { 20 return this.$store.getters.currentDay 21 } 22 } 23} 24</script>
試したこと
エラーの原因としては、すでにdata
にyear
,month
,day
が指定されているにも関わらず、computed
にも同様に指定されているためと考えられます。year
,month
,day
をそれぞれひとまとめにできればエラーが解消されると推測していますが、うまくいきません。試しにdata
の定数名とmethod
の定数名を別の名前にしてみたところ、store
のstate
から生年月日を参照でき、選択内容を2ページ目に表示できたのですが...
javascript
1data() { 2 return { 3 dataYear: 2000,//year → dataYearに変更 4 dataMonth: 1,//month → dataMonthに変更 5 dataDay: 1,//day → dataDayに変更 6 daysMax: '' 7 } 8//(中略) 9methods: { 10 getDays: function() {//year → dataYear, month → dataMonthにそれぞれ変更 11 this.daysMax = new Date(this.dataYear, this.dataMonth, 0).getDate(); 12 } 13} 14
今度はdata
の初期値とv-model
との関係がなくなってしまい、初期状態で2000(平成12)年1月1日が表示されず、月末の日にち計算がおかしくなってしまいました。(例えば、本来あり得ない2月31日が表示可能になってしまう)
select
の内容を別のページに表示しつつ、初期値の表示、月末の日にち計算する方法を教えてください。
追記1
v-modelをdateに合わせる、初期値を受け皿の変数date…に代入する
というコメントをいただきました。コメントに基づき、以下のように修正しました。
HTML
1<form> 2 <select v-model="date" @change="getDays"><!--dataYear → dateに変更--> 3 <option v-for="n in 100" v-bind:value="n + 1921" v-bind:key="n">{{(n + 1921) | era}}</option> 4 </select>年 5 <select v-model="date" @change="getDays"><!--dataMonth → dateに変更--> 6 <option v-for="n in 12" v-bind:key="n">{{n}}</option> 7 </select>月 8 <select v-model="date" @change="getDays"><!--dataDay → dateに変更--> 9 <option v-for="n in daysMax" v-bind:key="n">{{n}}</option> 10 </select>日 11</form>
javascript
1data() { 2 return { 3 date: moment("2000-01-01").toDate(),//dataYear,dataMonth,dataDayから変更 4 daysMax: '' 5 } 6//(中略) 7methods: { 8 getDays: function() {//合わせてdataYear → date.getFullYear(), dataMonth → date.getMonth()にそれぞれ変更 9 new Date(this.date.getFullYear(), this.date.getMonth(), 0).getDate(); 10 } 11}
しかし、初期値の表示、月末の日にち計算はできませんでした。エラー内容は以下の通りです。
v-on handler: "TypeError: this.date.getFullYear is not a function"
getFullYearとgetMonthを使用するにあたり、moment("2000-01-01").toDate()でdateをdateObjに合わせたので、問題ないように思うのですが...
補足情報(FW/ツールのバージョンなど)
Vue version: 2.6.14
Vue-CLI version: 4.5.14
回答1件
あなたの回答
tips
プレビュー