# 日報(2024-11-25) Vue でコンテキストメニューを使う世界一かんたんな方法
# はじめに
右クリックで自分が書いたメニューを出したいんだけど、ライブラリの追加とか嫌だし、難しい理屈を学ぶ脳力ないし CSS なんか書きたくない、とにかく当たり前の事だけでコンテキストメニューを出したいんだけどどうしよう、というfront 嫌いにありがちな雑なモチベーションです
# デモ動画
こういうのをつくります
# リストアイテムに出したいメニューを追加する
たとえばこんな list item があったとして
<template>
<v-list-item
@click="$emit('selected', index)"
>
<v-list-item-content
>
<v-list-item-title v-text="title"></v-list-item-title>
</v-list-item-content>
</v-list-item>
</template>
これを右クリックした時にブラウザの標準のコンテキストメニューじゃなくて、下のみたいな独自のメニューを出したいとします
<ul>
<li><a href="#">menu1</a></li>
<li><a href="#">menu2</a></li>
<li><a href="#">menu3</a></li>
</ul>
# 超シンプルな解決策
だったら、そのメニューを list item にほうりこんじゃえばよくて
<template>
<v-list-item
@click="$emit('selected', index)"
>
<v-list-item-content
>
<v-list-item-title v-text="title"></v-list-item-title>
</v-list-item-content>
<ul>
<li><a href="#">menu1</a></li>
<li><a href="#">menu2</a></li>
<li><a href="#">menu3</a></li>
</ul>
</v-list-item>
</template>
これでユーザーに必要な選択肢を提示できているのでこれでもいいと思うのですが、これを 右クリックしたときだけ 表示されるようにしたいとすると
# 右クリックした時だけメニューを表示する
# 1. v-show ディレクティブを使って条件を満たすときだけメニューを表示する
まず isContextMenuShown という変数を用意して、v-show ディレクティブを使って isContextMenuShown が真になった時だけ表示されるようにします
初期値は false にしておきましょう
<template>
<v-list-item
@click="$emit('selected', index)"
>
<v-list-item-content
>
<v-list-item-title v-text="title"></v-list-item-title>
</v-list-item-content>
<ul v-show="isContextMenuShown">
<li><a href="#">menu1</a></li>
<li><a href="#">menu2</a></li>
<li><a href="#">menu3</a></li>
</ul>
</v-list-item>
</template>
<script>
export default {
data: () => ({
isContextMenuShown: false,
}),
}
</script>
# 2. @click.right を使って右クリックをキャプチャーする
あとは、list item に @click.right を追加して右クリックをキャプチャーして、上で用意した isContextMenuShown を真にしてあげます
<template>
<v-list-item
@click.right="openContextMenu"
@click="$emit('selected', index)"
>
<v-list-item-content
>
<v-list-item-title v-text="title"></v-list-item-title>
</v-list-item-content>
<ul v-show="isContextMenuShown">
<li><a href="#">menu1</a></li>
<li><a href="#">menu2</a></li>
<li><a href="#">menu3</a></li>
</ul>
</v-list-item>
</template>
<script>
export default {
methods:{
openContextMenu(){
this.isContextMenuShown = !this.isContextMenuShown
}
},
data: () => ({
isContextMenuShown: false,
}),
}
</script>
なんてカンタンなんでしょう!
このままだと自分で定義したメニューと一緒にブラウザのコンテキストメニューもでてしまいます。ほとんどの場合、それが問題になるどころかそのほうがありがたかったりもするのですが、ブラウザのコンテキストメニューが無意味 な場合とかには抑止したいと思います
# 3.ブラウザの標準コンテキストメニューの抑止
@clik.right に .prevent をつけて右クリックがブラウザまで伝わらないように止めてしまいます
<template>
<v-list-item
@click.right.prevent="openContextMenu"
@click="$emit('selected', index)"
>
<v-list-item-content
>
<v-list-item-title v-text="title"></v-list-item-title>
</v-list-item-content>
<ul v-show="isContextMenuShown">
<li><a href="#">menu1</a></li>
<li><a href="#">menu2</a></li>
<li><a href="#">menu3</a></li>
</ul>
</v-list-item>
</template>
<script>
export default {
methods:{
openContextMenu(){
this.isContextMenuShown = !this.isContextMenuShown
}
},
data: () => ({
isContextMenuShown: false,
}),
}
</script>
Voilà !
# 感想
わかりやすいにこしたことないと思うんですよ