v-if/v-showと$vuetify.breakpointを使ってうまくレスポンシブができなかった件


こんにちは、Yuiです。

皆さんVue.jsでスマホのみサイドメニューなどを非表示にしたい場合、どうしていますか?
多分色々とやり方があるとは思うのですが、私はいつも表示非表示の切り替えは個人的に一番楽なv-if/v-showを使っています。

そして画面サイズによって表示・非表示を切り替えるために、v-if="$vuetify.breakpoint.xs"というような形で簡単にレスポンシブを組んでいます。

今回、いつものようにv-if/v-show$vuetify.breakpointを組み合わせて表示非表示を切り替えようとしたら、うまくいかなかったので、代わりにscssで調整した方法をまとめます。

$vuetify.breakpointとは?

そもそも、$vuetify.breakpointとはどのような書き方かというと、Vuetifyでは下記のように画面サイズがあらかじめ決められており、例えばv-if="$vuetify.breakpoint.xs"と書くことで、その要素をスマホのみ表示にすることができます。


Vuetifyドキュメントより

ちなみに、v-ifとv-showの切り替えは、v-ifがあまり頻繁に切り替えないとき、v-showは頻繁に表示非表示を切り替える場合に使うのが良いとされています。(v-ifの方が切り替えの際に負荷がかかる。)

今回起こった問題

まずはこちらを見てください。

ボタンが押すとサイドコンテンツが表示されますが、その後、ボタンが消えています。

今回は、ヘッダーの下に紫色の「開く」のボタンを置いて、そのボタンを置くとサイドコンテンツが表示されるようにしています。

PC版では、サイドコンテンツはデフォルトで表示をしているため、このボタンは表示する必要がありません。
なので、スマホでのみ表示にするためにこのように書きました。

App.vue
<v-btn v-if="$vuetify.breakpoint.xs"
 color="purple"
 dark
 @click.stop="drawer = !drawer"
>
   開く
</v-btn>

〜〜〜〜
<v-navigation-drawer
 v-model="drawer"
 absolute
 right
>
 <SideComment/>
</v-navigation-drawer>

※サイドコンテンツはページをわけて、SideComment.vueとして作っています。

表示を見ると、上記の通りボタンは無事スマホでのみ表示されるものの、一度しか押せなくなってしまいました。ちなみに、今回はPCとスマホは頻繁に切り替わることもないとv-ifを使っているのですが、v-showを使っても一度きりしか押せないのは変わりませんでした。

どうやらv-if/v-show@clickの動きは併用できないようです。
※もし併用できる方法を御存知の方はひっそりと私に耳打ちしてください。笑
(少なくとも色々と調べた限りでは、v-if/v-show@clickの動きを併用するのはあまり一般的ではないようでした。)

どうしたか

v-if/v-showが使えないとなると、scssでdisplay設定をするしかありません。
ということで、下記

App.vue
<v-btn v-if="$vuetify.breakpoint.xs"
 class="sp-visible"
 color="purple"
 dark
 @click.stop="drawer = !drawer"
>
   開く
</v-btn>

〜〜〜〜
<style lang="scss" scoped>
 $pc-min: 960px;
 @mixin display_pc {
   @media (min-width: $pc-min) {
     @content;
   }
 }
 .sp-visible {
   @include display_pc {
     display: none !important;
   }
 }
</style>

クラス名をつけて、そこにscssを適用させています。
@mixinははじめて使ったのですが、かなり便利でした。(参考:Sassの「@mixin(ミックスイン)」の使い方と「引数」の解説

今回はタブレットの表示はとりあえずおいておいて、とりあえずPCでのみ非表示にすることが目的だったので、このようなざっくりとしたブレイクポイントで設定しました。

完成形

このような感じで、ボタンは押しても消えなくなったので、とりあえずは成功です。

もちろん、このままではまだまだレスポンシブとして不完全なので、引き続きレイアウトは整えますが、とりあえずは目標達成です!やったね!

今回@mixinにかなり感動したので、またまとめたいと思います。