本記事はVuetify.jsのv1.5.x系の記法について考察したものです。
内容の最新更新日は2019/12/10です。
環境
Vuetify.js: v1.5.x
はじめに
Vuetifyのv-tooltipを使おうとして、公式ドキュメントのサンプルコードを目にしました。
<v-tooltip bottom>
<template v-slot:activator="{ on }">
<span v-on="on">This text has a tooltip</span>
</template>
<span>Tooltip</span>
</v-tooltip>
とりあえずコピペで使えますが、
「v-slot:activator="{ on }"
は何なのか」「v-on="on"
ってなにやってるの???」
という風に疑問を持ったので調べてみました。
v-slot:activatorとは
まず、前半のv-slot:activator
はv-tooltipからactivatorというスロットを取得するという意味でした。
もう一回公式ドキュメントを見てみましょう。
APIのところにPROPSとSLOTSがありますよね?(←今まで気づかなかった💦)
SLOTSにはactivatorとdefaultの二種類のスロットがありました。
そう、このactivatorがv-slot:activator
のactivatorなんです。
v-slot:activator
は名前付きスロットの書き方です。
<template v-slot:activator="{ on }">
を<template #activator="{ on }">
に略すこともできます。
ちなみに、v-slotはtemplateでしか使えません。
#activator="{ on }"とは
activatorのヒントを掴んだところで、後半の="{ on }"
の謎に迫っていきます。
鋭い方はお気づきかと思いますが、activatorのPropsには、こういう記述がありました。
{
on: { [eventName]: eventHandler }
value: boolean
}
onだ!!!
onはスロットactivatorのプロパティなのです!
「でもそれって、#activator="{ on }"
と何の繋がりがあるの?」
今度はVue.js公式のドキュメントからv-slotの記述を見てみます。
こんな書き方があったではないですか!
<!-- 分割代入でプロパティを受け取るデフォルトスロット -->
<mouse-position v-slot="{ x, y }">
Mouse position: {{ x }}, {{ y }}
</mouse-position>
そう、"{ on }"
は分割代入の書き方だったのです!
厳密的ではないですが、噛み砕くとこんな役割があります。
- スロットactivatorから
プロパティon
を受け取る - 分割代入(
変数on
にプロパティon
を代入)する - スロット内で
変数on
が利用可能になる
では、気になるonの中身は?
activatorのイベントリスナーでした。
SLOTS - activator - Descriptionを引用します。
When used, will activate the component when clicked (or hover for specific components).
スロットactivatorはClickイベント(もしくはHoverイベント)に反応します。
v-tooltipだと、Hoverイベントが対象になると考えられます。(そのため、ポインターを重ねる時に反応する)
実際に入っているイベントリスナーを確認していないので、気になる方はご自身でお調べください。
v-on="on"とは
<template v-slot:activator="{ on }">
がやっていることが分かりました。今度は<span v-on="on">
を見ていきます。
Vue.js公式のドキュメントのv-onにこんな構文が書かれていました。
<!-- オブジェクト構文 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
v-on:[event]
/@[event]
以外の書き方は初めて知りました。
どうやらオブジェクト構文を使用するとイベントの種類を指定しなくても、オブジェクトの中身で指定できます。
(そうすることによって複数のイベントハンドラーを一気に指定できます)
さて、これを踏まえて、もう一回振り返りましょう。
activatorのPropsのonの定義がこうなります。
on: { [eventName]: eventHandler }
つまりv-on="on"
はv-on="{ [eventName]: eventHandler }"
で、上記のオブジェクト構文に当てはまります。
余談ですが、@on
に省略できないか試してみましたが、
v-on:on="eventHandler"
ではないので、当然エラーになります。
参考資料
[Documentation] v-slot:activator="{ on }" #6866
このIssueがものすごく参考になりました!
おかげでモヤモヤ解消しました。
さいごに
自分なりに解読して考察してみたんですが、
納得できる答えを出せたのはやはり上記のIssueのおかげだと思います。
しかし英語の解読力とフレームワークの構造自体に対する理解に自信がなくて、
自分なりの解釈でなんとか説明してみたものの、正確さが欠けている部分があると思います。
ご指摘、ご指導をいただけたら幸いです。