Vuetify使っててv-onとかv-bindをたくさん指定したい

# まえおき

この投稿は[木更津高専アドカレ](https://qiita.com/advent-calendar/2022/nit_kisarazu) 飛び込み18日目の記事でーす！

<< prev-17日目 [AtCoder入緑したよ](https://qiita.com/ku_senjan/items/e675e3099c4cd0a39ed2) by @ku_senjan 
\>> next-19日目 [Discordで勉強時間記録botを作る](https://qiita.com/kokastar/items/1fcb171933fb245ad8ab) by @kokastar 

# dialogとかtooltipとか使いたいのよ
こんにちは、Vuetifyで遊んでいたらNuxtがVue3に正式対応になっていて、Composition APIを学びたいなあとなっているtos_upです。

Vuetifyって面白いですよね。ぼくは大好きです。

さて、`<v-tooltip>`と`<v-dialog>`を一つのボタンに重ねがけたい私は、一つの要素に`v-bind`、`v-on`を重ねる方法を知らなくて困っていました。

というところからお話は始まります。
※要は備忘録です。

# 結論
長い説明をするので、結果だけ聞きたい人にはこちらです。
``` html
<v-dialog v-model="dialog">
  <template #[`activator`]="{ on: dialogOn, attrs: dialogAttrs }">
  <!-- on: (任意のon名), attrs: (任意のbind名) -->
    <v-tooltip bottom>
      <template #[`activator`]="{ on: tooltipOn, attrs: tooltipAttrs }">
      <!-- on: (任意のon名), attrs: (任意のbind名) -->
        <v-btn v-bind="{dialogAttrs, tooltipAttrs}" v-on="{...dialogOn, ...tooltipOn}">アップロード</v-btn>
        <!-- v-bind="{(1つめのattrs), (2つめのattrs)}" v-on="{...(1つめのon), ...(2つめのon)}" -->
      </template>
    </v-tooltip>
  </template>
</v-dialog>
```

---

# そもそも

私「`` <template #[`activator`]="{ on, attrs }"> ``って何やってるの」
私が調べたVue公式「(ｼｰﾝ)」

ちゃんと調べたら公式サイトに載っているのかもしれません。
検索英語が下手な私は辿り着くことができませんでした。

なのでコードで検証してみましょう。

環境はこちらです。

<details><summary>環境</summary>

```
node: v16.18.1

nuxt: v2.15.8
vue: v2.7.10
vuetify: v2.6.10
```

</details>

## 検証①

```html:template in test.vue
<v-dialog>
  <template #[`activator`]="{ on, attrs }">
    <v-btn v-on="on" v-bind="attrs" @click="showAny(on, attrs)">
    </v-btn>
  </template>
</v-dialog>
```

```ts:script in test.vue
// 中略
  showAny(on: any, attrs: any): void {
    console.log('on is ', on);
    console.log('attrs is ', attrs);
  }
// ---
```

**出力**

![出てきたもの](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386109/ee02327a-55df-a619-9f65-7774038e43ea.png)

ここからわかる情報は
> `on`にはclickのハンドラが入っていること
> from https://vuetifyjs.com/ja/api/v-dialog/#slots-activator

> `attrs`にはアクセシビリティの情報が入っていること
> from https://qiita.com/Gedyra/items/9d05e10329808367396f

ということでした。

## 複数指定はどうやるの

### 失敗例

https://v2.vuejs.org/v2/guide/class-and-style.html#Array-Syntax-1

上のサイトを参考にして、以下のコードを書きました。

```html:Failed.vue

<v-btn v-bind="[dialogAttrs, tooltipAttrs]" v-on="[dialogOn, tooltipOn]">

```

私「ﾎﾞﾀﾝﾎﾟﾁｰ」

動きませんでした。

attrsは増えていません。

![増えないattrs](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386109/6287df16-990e-879b-e919-fa810b02b0f2.png)

エラーも出ています。

![エラーが出たよ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386109/66acec1e-c112-62c6-8d45-21576ff38383.png)

原因を探っていきましょう。

#### 原因①: attrsが増えない

結論から言うと、原因まではわかりませんでした。

というか動作に支障をきたすのかどうかすらもわかりませんでした。

ですが、もとはObjectだったので`[]`のかわりに`{}`で囲ってObjectにしてあげたところ、画像のようになりました。

![Screenshot 2022-12-18 at 20.11.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2386109/2e1c0429-a073-5fb0-bef0-f3668fbe1ddb.png)

#### 原因②: v-onのエラー

動かない原因はこっちだと思います。

多分`v-on`を複数指定できていないのが原因ですね。

### 解決?

ここで、v-onについて、こんな記事を見つけてしまいました。

https://jp.vuejs.org/v2/api/index.html#v-on

```html
<!-- オブジェクト構文 (2.4.0+) -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
```

そういうことだったんですね。

と思って書いたコードは失敗でした。

```html:Failed.vue
<v-btn v-on="{dialogOn, tooltipOn}"  ... >
```

動きません。

### 成功へ

エラーも出ず、いよいよわからなくなってしまったところ

https://github.com/vuetifyjs/vuetify/issues/6866#issuecomment-843413507

見つけてしまいました。

```html
<template v-slot:activator="{ on }">
  <my-comp v-on="{...on, ...$listeners}" />
</template>
```

という記述をもとに

```html:Success.vue
<v-btn v-on="{...dialogOn, ...tooltipOn}" v-bind="{dialogAttrs, tooltipAttrs}"></v-btn>

```

動いたー！！！

# 参考

この問題を解決するにあたって、参考にさせていただいたサイトです。

https://stackoverflow.com/questions/60809725/merging-multiple-v-slotactivator-and-v-on-in-vuetify-templates

https://mashoo1101.hatenablog.com/entry/2022/03/05/172305

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

# 成功のコード
https://github.com/tos-up/Qiita-records/tree/main/vuetify_multiple_on_attrs