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

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

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

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

Vuex

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

Q&A

解決済

1回答

557閲覧

App.vueからVuexのstoreにアクセスできない

addyson

総合スコア24

Vue.js

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

Vuex

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

0グッド

0クリップ

投稿2022/09/24 11:34

前提

Vuexを使用して状態管理を行い、ドロップダウンメニューを作成しています。

実現したいこと

ナビゲーションバー(ヘッダー)に設置しているユーザーアイコンをクリックするとドロップダウンが開き、ドロップダウンが開いた状態でウィンドウのどこかをクリックすると閉じられる。という処理を実装したいです。

発生している問題・エラーメッセージ

ドロップダウンを開く処理をNavigationBar.vueに、閉じる処理をApp.vueに記述しているのですが、App.vueからstoreにアクセスしようとした場合のみundefinedとなり失敗してしまいます。

Uncaught TypeError: Cannot read properties of undefined (reading 'state')

該当のソースコード

storeの定義をstore.jsで行い、それをmain.jsでインポートしています。
App.vueでNavigationBar.vueをインポートしており、ドロップダウンを開くときはNavigatioBar.vueのopenDropDownが実行され、閉じるときはApp.vueのaddEventListenerToCloseDropDownで設置したイベントによって閉じられるという想定です。
開く処理は正常に実行されるのですが、閉じる処理で上記のエラーが発生してしまいます。

src/main.js

javascript

1import Vue from 'vue'; 2import App from '@/App.vue'; 3import '@/assets/css/tailwind.css'; 4import router from '@/router'; 5import axios from '@/plugins/axios'; 6import VeeValidate from '@/plugins/vee-validate'; 7import store from '@/plugins/store'; 8 9if(process.env.VUE_APP_ENV_MODE === 'development') { 10 Vue.config.productionTip = true; 11} else { 12 Vue.config.productionTip = false; 13} 14 15new Vue({ 16 router, 17 axios, 18 VeeValidate, 19 store, 20 render: h => h(App), 21}).$mount('#app'); 22

src/store.js

javascript

1import Vue from 'vue'; 2import Vuex from 'vuex'; 3 4Vue.use(Vuex); 5 6const store = new Vuex.Store({ 7 strict: process.env.NODE_ENV !== 'production', 8 state: { 9 dropDownIsOpen: false 10 }, 11 mutations: { 12 openDropDown(state) { 13 state.dropDownIsOpen = true 14 }, 15 closeDropDown(state) { 16 state.dropDownIsOpen = false 17 } 18 }, 19 actions: { 20 21 }, 22 getters: { 23 24 } 25}) 26 27export default store;

src/App.vue

javascript

1<template> 2 <div id="app" class="flex flex-row"> 3 <NavigationBar /> 4 <router-view class="mt-14" /> 5 </div> 6</template> 7 8<script> 9import NavigationBar from './components/NavigationBar.vue' 10 11export default { 12 name: 'App', 13 components: { 14 NavigationBar 15 }, 16 mounted() { 17 this.addEventListenerToCloseDropDown(); 18 }, 19 methods: { 20 addEventListenerToCloseDropDown() { 21 window.document.addEventListener('click', function() { 22 if(this.$store.state.dropDownIsOpen) { 23 this.$store.commit('closeDropDown'); 24 } else if(this.$store.state.dropDownIsOpen === false) { 25 ; 26 } 27 }) 28 } 29 } 30} 31</script> 32

src/components/NavigationBar.vue

javascript

1<template> 2 <header class="fixed w-full h-14 bg-white py-2.5 px-6 flex justify-between border-b-2 border-gray-200"> 3 <router-link to="/" class="text-3xl text-black font-bold">Kiite</router-link> 4 <nav class="flex flex-end items-center space-x-4 text-gray-500"> 5 <router-link to="/articles">記事</router-link> 6 <router-link to="/">チャット</router-link> 7 <button class="h-full" @click="openDropDown()"> 8 <img src="@/assets/icon-sample.png" alt="" class="h-full object-contain"> 9 </button> 10 <router-link to="" class="flex items-center justify-center bg-blue hover:bg-blue-dark text-white rounded-lg w-20 h-8"> 11 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 43.536 43.471" class="h-4"> 12 <path d="M9.8,45.055H11.98L37.856,19.12l-2.24-2.181L9.8,42.816ZM45.872,16.645,38.151,8.923l2.358-2.358a3.628,3.628,0,0,1,2.741-1.09,4.04,4.04,0,0,1,2.8,1.149l2.24,2.181a3.5,3.5,0,0,1,1.09,2.77,4.027,4.027,0,0,1-1.208,2.711ZM8.208,48.946A2.316,2.316,0,0,1,5.85,46.588V42.226a2.221,2.221,0,0,1,.177-.884,2.447,2.447,0,0,1,.53-.766L35.675,11.4,43.4,19.061,14.279,48.238a2.355,2.355,0,0,1-.8.53,2.439,2.439,0,0,1-.914.177ZM36.8,18,35.616,16.94l2.24,2.181Z" transform="translate(-5.85 -5.474)" fill="#ffffff"/> 13 </svg> 14 <span class="leading-4 ml-1.5">投稿</span> 15 </router-link> 16 <div v-if="this.$store.state.dropDownIsOpen" class="absolute bg-white top-16 right-28 py-2 border shadow-xl rounded-lg"> 17 <ul class="w-full h-full text-black"> 18 <li class="hover:bg-gray-100 w-full h-8 px-3 leading-8"><router-link :to="{ name: 'userHome', params: {user_id: this.currentUserId} }" class="block w-full">{{ this.currentUser.name }}</router-link></li> 19 <li class="hover:bg-gray-100 w-full h-8 px-3 leading-8"><router-link :to="{ name: 'settingsAccount' }" class="block w-full">アカウント設定</router-link></li> 20 </ul> 21 </div> 22 </nav> 23 </header> 24</template> 25 26<script> 27import axios from 'axios'; 28 29export default { 30 data() { 31 return { 32 currentUser: "", 33 currentUserId: "" 34 } 35 }, 36 mounted() { 37 this.setCurrentUserId(); 38 this.setUser(); 39 }, 40 methods: { 41 setCurrentUserId() { 42 this.currentUserId = localStorage.getItem('current_user_id'); 43 }, 44 setUser() { 45 axios.get(process.env.VUE_APP_API_BASEURL + '/users/' + this.currentUserId) 46 .then((response) => { 47 this.currentUser = response.data; 48 }); 49 }, 50 openDropDown() { 51 this.$store.commit('openDropDown'); 52 } 53 } 54} 55</script>

補足情報(FW/ツールのバージョンなど)

vue: 2.6.14
vuex: 3.6.2

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

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

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

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

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

guest

回答1

0

自己解決

問題の原因は記述しているファイルがApp.vueであることではなく、関数内の処理が悪かったようです。
下記のように修正したら意図した通りの動作をするようになりました。

javascript

1 addEventListenerToCloseDropDown() { 2 window.addEventListener('click', this.closeDropDown = (event) => { 3 const navigationBarIcon = document.getElementById('navigation-bar-icon'); 4 if (event.target !== navigationBarIcon && this.$store.state.dropDownIsOpen === true) { 5 this.$store.commit('closeDropDown'); 6 } else { 7 ; 8 } 9 }); 10 }

投稿2022/10/05 10:09

addyson

総合スコア24

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問