## 背景
以下のような`components/Counter.vue`があるとする。
```html
<script setup lang="ts">
import { ref } from "vue";
const count = ref(0);
const increment = () => {
count.value++;
};
</script>
<template>
<div>{{ count }}</div>
<button @click="increment">+</button>
</template>
```
`Counter.vue`を利用している`App.vue`が以下。
```html
<script setup lang="ts">
import Counter from "./components/Counter.vue";
</script>
<template>
<div style="padding: 12px">
<Counter />
</div>
<button>プラス</button>
</template>
```
この『プラス』ボタンが押されたときに`Counter`の中のカウンターをインクリメントさせたい。しかし、Counterの値を`App.vue`では保持せず、`Counter.vue`の中で定義された`increment`関数を呼び出したい。
## 方法
[[defineExpose]]を使って`increment`関数を公開し、[[Template refs]]を使って`Counter.vue`インスタンスのメソッドにアクセスし、実行する。
`App.vue`
```html
<script setup lang="ts">
import { ref } from "vue";
const count = ref(0);
const increment = () => {
count.value++;
};
// これを追加
defineExpose({
increment,
});
</script>
<template>
<div>{{ count }}</div>
<button @click="increment">+</button>
</template>
```
`Counter.vue`
```html
<script setup lang="ts">
import { ref } from "vue";
import Counter from "./components/Counter.vue";
// Counterのインスタンスをref経由で取得
const counterEl = ref<InstanceType<typeof Counter> | null>(null);
</script>
<template>
<div style="padding: 12px">
<!-- refに先ほど指定した変数名を指定 -->
<Counter ref="counterEl" />
</div>
<!-- コンポーネントでexposeしたIFを利用できる -->
<button @click="counterEl?.increment()">プラス</button>
</template>
```
## 参考
- https://vuejs.org/guide/essentials/template-refs