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

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

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

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

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

Vuetify.js

Vuetify.jsは、マテリアルデザインを基本とするVue.jsのCSSフレームワークです。多くのマテリアルデザインのコンポーネントを提供しており、あらゆるアプリケーションに対応可能。vue-cli用テンプレートがあり、簡単にページを作成できます。

Vuex

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

Q&A

解決済

3回答

984閲覧

Nuxt.jsのstore内にて、vuetifyの変数を使用したい

pen_ari

総合スコア50

Vue.js

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

Nuxt.js

Nuxt.jsは、ユニバーサルなSPAが開発可能なVue.jsベースのフレームワーク。UIの描画サポートに特化しており、SSRにおけるサーバーサイドとクライアントサイドのUIレンダリングなどさまざまな機能を持ちます。

Vuetify.js

Vuetify.jsは、マテリアルデザインを基本とするVue.jsのCSSフレームワークです。多くのマテリアルデザインのコンポーネントを提供しており、あらゆるアプリケーションに対応可能。vue-cli用テンプレートがあり、簡単にページを作成できます。

Vuex

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

0グッド

0クリップ

投稿2020/08/15 05:32

前提・実現したいこと

Nuxt.jsのstore内にて、vuetifyの変数を使用したいです
具体的にはモジュールモードで記載したstoreのgettersとして、画面が小さいか大きいかを返す関数を定義し、
各コンポーネントではそれを参照することで、レスポンシブ対応したいです
(なんでそんな事やってるの?こうした方が良くない?等有りましたら教えて下さい)

該当のソースコード

javascript

1// /store/windowSize.js 2export const state = () => ({}) 3 4export const getters = { 5 isSmall: () => 6 this.$vuetify.breakpoint.width < this.$vuetify.breakpoint.thresholds.sm, 7}

vue

1 2<template> 3 <p v-if="isSmall">小さい画面</p> 4 <p v-else>大きい画面</p> 5</template> 6 7<script> 8import { mapGetters } from 'vuex' 9export default { 10 computed: { 11 ...mapGetters('windowSize', ['isSmall']), 12 }, 13} 14</script> 15

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

TypeError: Cannot read property '$vuetify' of undefined at isSmall (windowSize.js:4) at wrappedGetter (vuex.esm.js:877) at Vue.<anonymous> (vuex.esm.js:140) at Watcher.get (vue.runtime.esm.js:4479) at Watcher.evaluate (vue.runtime.esm.js:4584) at Vue.computedGetter [as windowSize/isSmall] (vue.runtime.esm.js:4836) at Object.get [as windowSize/isSmall] (vuex.esm.js:667) at VueComponent.mappedGetter (vuex.esm.js:1022) at Watcher.get (vue.runtime.esm.js:4479) at Watcher.evaluate (vue.runtime.esm.js:4584)

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

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

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

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

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

guest

回答3

0

ベストアンサー

とりあえず一番初めに書くだろうカウンタアプリを少しだけVuetifyっぽく書いてみました。
結論から言うと、store(Vuex)からVuetifyは普通には見えません。
今回は最上位のVueで、特定のstoreインスタンスに$vuetifyを無理矢理埋め込みました。

html

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet"> 6 <link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet"> 7 <link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet"> 8 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"> 9</head> 10 11<body> 12 <div id="app"></div> 13</body> 14<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> 15<script src="https://unpkg.com/vuex"></script> 16<script src="https://unpkg.com/vuex"></script> 17<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script> 18<script> 19 Vue.use(Vuex); 20 Vue.use(Vuetify); 21 const store = new Vuex.Store({ 22 state: { 23 count: 0, 24 }, 25 mutations: { 26 increment(state) { 27 console.log('from store'); 28 console.log(this.$vuetify); 29 state.count++; 30 } 31 } 32 }); 33 const Counter = { 34 name: 'Counter', 35 template: `<v-card> 36 <v-card-title>{{count}}</v-card-title> 37 <v-card-actions @click="increment()"> 38 <v-btn text>increment</v-btn> 39 </v-card-actions> 40 </v-card>`, 41 computed: { 42 count: function () { 43 return this.$store.state.count; 44 }, 45 }, 46 methods: { 47 increment: function () { 48 console.log('from counter'); 49 console.log(this.$vuetify); 50 this.$store.commit('increment'); 51 }, 52 } 53 }; 54 new Vue({ 55 template: `<v-app class="app"> 56 <v-main> 57 <v-container> 58 <counter/> 59 </v-container> 60 </v-main> 61 </v-app>`, 62 el: "#app", 63 store: store, 64 vuetify: new Vuetify(), 65 components: { 66 "counter": Counter, 67 }, 68 created: function() { 69 // 無理矢理入れる 70 this.$store.$vuetify = this.$vuetify; 71 } 72 }); 73</script> 74 75</html>

追記

長々と書くのもアレだったので短く書きすぎました。解決後ですが追記しておきます。

まず、nuxt.jsを使ったもので説明します。
npx create-nuxt-app sample-nuxtを↓な感じで作ります。

text

1create-nuxt-app v3.2.0 2✨ Generating Nuxt.js project in sample-nuxt 3? Project name: sample-nuxt 4? Programming language: JavaScript 5? Package manager: Npm 6? UI framework: Vuetify.js 7? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection) 8? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection) 9? Testing framework: None 10? Rendering mode: Single Page App 11? Deployment target: Server (Node.js hosting) 12? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)

次に以下のファイルを作ったり、置き換えたりします。

pages/index.vue

vue

1<template> 2 <v-container> 3 <counter /> 4 </v-container> 5</template> 6 7<script> 8import Counter from "~/components/Counter.vue"; 9 10export default { 11 components: { 12 Counter, 13 }, 14}; 15</script>

components/Counter.vue

vue

1<template> 2 <v-card> 3 <v-card-title>{{ count }}</v-card-title> 4 <v-card-actions> 5 <v-btn text @click="increment()">increment</v-btn> 6 <v-btn text @click="push()">push</v-btn> 7 </v-card-actions> 8 </v-card> 9</template> 10 11<script> 12import { mapMutations, mapGetters } from 'vuex' 13 14export default { 15 name: "Counter", 16 computed: { 17 count: function () { 18 return this.$store.getters['counterstore/count']; 19 }, 20 }, 21 methods: { 22 increment: function () { 23 console.log("vue_component: this.$vuetify=" + this.$vuetify); 24 this.$store.commit("counterstore/increment"); 25 }, 26 push: function () { 27 this.$store.commit("counterstore/push", this.$vuetify); 28 }, 29 }, 30}; 31</script>

store/counterstore.js

javascript

1export const state = () => ({ 2 counter: 0 3}) 4 5export const mutations = { 6 increment(state) { 7 state.counter++; 8 console.log("store_increment: this.$vuetify =" + this.$vuetify); 9 }, 10 push(state, args) { 11 // 無理矢理受け渡す 12 this.$vuetify = args; 13 console.log("store_push: this.$vuetify is set!"); 14 } 15} 16 17export const getters = { 18 count(state) { 19 if (this != null) { 20 console.log('store_getters: this.$vuetify =' + this.$vuetify); 21 } else { 22 console.log('store_getters: this =' + this); 23 } 24 return state.counter; 25 }, 26}

動かすと、初期画面がこんな感じになります。
イメージ説明

consoleの表示は、

text

1store_getters: this =undefined

な感じです。gettersでは呼出元が関数呼出してるので、thisが入っていません。
まずgettersを使うとthis.$vuetifyは無理なのですよ。

次にINCREMENTボタンを押します。するとconsoleは

text

1vue_component: this.$vuetify=[object Object] 2store_increment: this.$vuetify =undefined 3store_getters: this =undefined

と出ています。vueコンポーネントからはthis.$vuetifyが入っていますが、生成時にプラグインからそういうのを入れるカラクリがないstoreにはthis.$vuetifyが入っていないのが分かります。

仕方がないので実装したPUSHボタンを押すと...

text

1store_push: this.$vuetify is set!

引数で無理矢理コンポーネントから参照してたvuetifyのインスタンスを渡されるので、storeにvuetifyが設定されます。

再度INCREMENTを押すと...

text

1vue_component: this.$vuetify=[object Object] 2store_increment: this.$vuetify =[object Object] 3store_getters: this =undefined

store側のincrementでthis.$vuetifyが入ってることが分かります。getterでは相変わらず見えませんが...

つまり、Vueコンポーネントでは見えるthis.$vuetifyも、Vuexからはインスタンス生成しただけでは見えないということです。またgettersからはどうやっても見えません(Vue.prototype.$vuetifyも駄目でした。今はそういう渡し方じゃないのかも)。で、それを伝えようとしたのが最初のコードだったわけです。なお、この辺TypeScriptだとまた事情が変わるかもです。そのクラス表記はさらに不明です。

長文失礼しました。詳しい部分じゃないので、間違ってたら指摘お願いします。

投稿2020/08/16 20:11

編集2020/08/17 06:23
dameo

総合スコア943

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

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

pen_ari

2020/08/17 12:57

大変丁寧にありがとうございます やはりvuetifyの変数をstoreで監視するというのはオーソドックスなやり方では無さそうですね 大変参考になりました! ありがとうございます
guest

0

質問タイトルへの回答としてdameoさんの回答がとても参考になりました
ありがとうございました

スマホからのためmdではなくご容赦ください
そもそも実現したかった、画面サイズに応じて表示を切り替えるというところについてですが、
ブレークポイントはxsやsmなどピンポイント該当するときだけtrueになるから、
v-if="$vuetify.breakpoint.xs || $vuetify.breakpoint.sm"
などと、複数サイズを列挙しなければいけないと勘違いして、それが嫌で記載したようなやり方を考えていたのですが、
色々調べた結果
v-if="$vuetify.breakpoint.smAndDown"
とすることで実現したかったことはできそうでした
https://qiita.com/rubytomato@github/items/aabc9ee7ba0ccee910b5

投稿2020/08/17 12:59

編集2020/08/17 13:11
pen_ari

総合スコア50

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

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

0

削除 誤回答のため

投稿2020/08/15 18:54

編集2020/08/17 00:58
nico25

総合スコア830

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

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

rubytomato

2020/08/16 23:20

vuex内からはvueインスタンスにアクセス出来ないと思っていたのですが動作確認済みでしょうか
nico25

2020/08/17 00:58

申し訳ございません、質問の意図を勘違いしておりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問