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

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

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

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

Vuex

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

解決済

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

addyson
alison

総合スコア24

Vue.js

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

Vuex

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

1回答

0グッド

0クリップ

210閲覧

投稿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

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答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

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

Vue.js

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

Vuex

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