Vuetifyのv-slot:activator="{ on, attrs }"についてメモ

v-slot:activator="{ on, attrs }" が何をやっているのか理解できなかったのでメモ。

<v-tooltip bottom>
  <template v-slot:activator="{ on, attrs }">
     <v-btn
       color="primary"dark
       v-bind="attrs"v-on="on">
      Button
     </v-btn>
  </template>
  <span>Tooltip</span>
</v-tooltip>

以下の記事を読めば解決しましたが理解を深めるため自分の言葉でまとめます。

https://qiita.com/aotoriii/items/06ae49c135061a12b75

slotとは

Vuetify云々の前にslotについておさらい。

slotは親コンポーネントから子供コンポーネントで使うコンポーネントを渡せるVueの機能。

シンプルなスロット

<!-- parent-component.vue -->
<div>
    <child-component>
    Hello World
    </child-component>
</div>

<!-- child-component.vue -->
<div>
  message: <slot></slot>
</div>

message: Hello World が表示される。

スコープ付きスロット

コンポーネントが持っているプロパティを、親コンポーネントslotの箇所で参照できるようになる。

<!-- parent-component.vue -->
<template>
  <div>
    <MyCom v-slot:bind-user="parentComponentUser">
      {{ parentComponentUser.user.name }}
    </MyCom>
  </div>
</template>
<script>
import MyCom from '../components/MyCom.vue'
export default {
  components: {
    ChildComponet
  }
}
</script>

<!-- child-component.vue -->
<template>
  <div class="mycom">
    <p>name:<slot v-bind:bind-user="user">{{ user.age }}</slot></p>
  </div>
</template>
<script>
export default {
  name: 'MyCom',
  data () {
    return {
      user: {
          name: 'sano',
         age: 100
      }
    }
  }
}
</script>

child-componentuserというslotを定義している。またbind-userにリアクティブなオブジェクトuserをバインドしている。

コンポーネントでは、bind-userparentComponentUserに渡され最終的にsano が表示される。

上記のslotの例と同様に、Vuetifyのコンポーネントはそのコンポーネントにイベントが発生した時に表示するコンテンツをslotを使って渡すことができる。

<v-tooltip bottom>
  <!-- slot開始-->
  <template v-slot:activator="{ on, attrs }">
     <v-btn
       color="primary"dark
       v-bind="attrs"v-on="on">
      Button
     </v-btn>
  </template>
  <!-- slot終了-->
  <span>Tooltip</span>
</v-tooltip>

toolchipのサンプルコードからは以下のことがわかる。

onとは

https://vuetifyjs.com/ja/api/v-tooltip/#slots

ドキュメントにはイベントハンドラーを持つオブジェクトとある。

on: { [eventName]: eventHandler },

実際に試してみる。

<v-tooltip bottom>
  <template #activator="{ on, attrs }">
    <v-btn color="primary" dark v-bind="attrs" v-on="on" @click="clickOn(on)"> Button </v-btn>   
  </template>
  <span>Tooltip</span>
</v-tooltip>

<script>
export default defineComponent({
  setup() {
    const clickOn = (on: any) => {
      console.log(on)
    }
    return {clickOn}
  }
})
</script>

f:id:mashoo1101:20220305170940p:plain

Buttonをクリックするとconsoleにイベントハンドラーを持つオブジェクトが表示される。

v-on="on"とは

https://qiita.com/aotoriii/items/06ae49c135061a12b75e#v-ononとは で全て解説されているので詳細をこちらを確認してください。

結論を書くとv-on="{ [eventName]: eventHandler }” のようにイベント名とイベントハンドラをかける、ということです。先のconsole.logで確認したVuetifyが提供するイベントハンドラーが登録されます。ホバーしたときにthipを表示するといったコンポーネントの挙動を決めてくれています。

v-bind="attrs"

attrsはアクセシビリティ関連のオブジェクト。

以下の記事に詳しくまとまっていた。

https://qiita.com/Gedyra/items/9d05e10329808367396f

value: boolean

https://vuetifyjs.com/ja/api/v-tooltip/#slots

ドキュメントには明確に記載されていないがイベントハンドラが呼ばれたかの情報と思われる。

valueとonを利用するとiconにホバーした時にtooltipを出し、且つiconの色をかえるといったことができる。

<v-tooltip bottom>
  <template #activator="{ on, attrs, value }">
    <v-icon
      medium
      class="ml-1"
      :color="value ? '#0068B7' : '#757575'"
      v-bind="attrs"
      v-on="on"
    >
      mdi-help-circle
    </v-icon>
  </template>
 thipに出るテキスト       
</v-tooltip>

f:id:mashoo1101:20220305172148p:plain f:id:mashoo1101:20220305172210p:plain

まとめ

Vuetifyのコンポーネントは、slotコンポーネントの中身をカスタマイズでき、そのカスタマイズする内容にコンポーネントの状態を含めることができる。Vuetifyすげ〜。