owned this note
owned this note
Published
Linked with GitHub
---
tags: vue3
---
# Vue3 - Composition API - Template Refs
# 📕 Template Refs
- [ref 예시 - jsFiddle](https://jsfiddle.net/yejin_yang/cr840Lha/5/)
자바스크립트로 자식 컴포넌트에 직접 접근해야하는 경우가 있다. 이럴 때는 reference ID를 자식 컴포넌트나 HTML element에 `ref` 속성을 부여해야 한다.
```htmlembedded
<input ref='inputTag' />
```
ref가 사용되는 예시는 input에 focus를 주어야 하는 경우일 것이다.
```javascript
new Vue({
el: "#app",
methods:{
focusInput(){
this.$refs.inputTag.focus();
}
},
mounted(){
this.focusInput();
},
})
```
부모 컴포넌트 쪽에서 ref를 컴포넌트에 부여하여, focusInput을 하게 할 수도 있다.
```htmlembedded
<base-input ref="usernameInput"></base-input>
```
```javascript
this.$refs.usernameInput.focusInput()
```
> Warning
`$refs`는 컴포넌트가 렌더링된 후에 생기게 된다. $refs를 템플릿에서나, computed property에서 접근하면 안된다.
# 📕 Composition API - Template Refs
- [Codesandbox 예시](https://codesandbox.io/s/vue3-composition-api-template-refs-9dupw?file=/src/App.vue)
컴포지션 API에서는 reactive refs와 template refs 개념이 합쳐지게 된다. template element나 컴포넌트에 있는 reference를 얻어내기 위해서는, 원래처럼 ref를 부여하고, `setup()`안에서 ref를 반환받아야 한다.
```htmlembedded
<template>
<div ref="root">this is root element</div>
<input ref="input" />
</template>
<script>
import { ref, onMounted } from "vue";
export default {
name: "App",
setup() {
const root = ref(null);
const input = ref(null);
onMounted(() => {
console.log(root.value); // <div>this is root element</div>
input.value.focus();
});
return {
root,
input,
};
},
};
</script>
```
render context(setup())에 `root`를 두고, `ref="root"`로 ref를 div에 바인드 시켰다. **Virtual DOM patching 알고리즘**에서 VNode의 ref 키가 render context에 있는 ref와 일치한다면, VNode의 해당 엘리먼트나 컴포넌트 인스턴스는 그 ref의 값을 할당받는다. 이 과정은 VDOM mount / patch 과정에서 이루어지게 된다. 따라서 template ref는 초기 렌더링 이후의 할당된 값만 얻을 수 있다.
template refs로 사용된 `refs`는 다른 refs들과 같은 방식으로 동작한다. 즉, **반응형**이며 compostion 함수에 전달될 수 있다.
## 📍 JSX와 사용하기
이건 뭔지 잘 모르겠넹...
```javascript
export default {
setup() {
const root = ref(null)
return () =>
h('div', {
ref: root
})
// with JSX
return () => <div ref={root} />
}
}
```
## 📍 `v-for` 안에서 사용하기
v-for 안에서 ref를 사용할 때는 function refs가 사용하여 처리할 수 있도록 해야 한다.
```htmlembedded
<template>
<div v-for="(item, i) in list" :ref="el => { if (el) divs[i] = el }">
{{ item }}
</div>
</template>
<script>
import { ref, reactive, onBeforeUpdate } from 'vue'
export default {
setup() {
const list = reactive([1, 2, 3])
const divs = ref([])
// make sure to reset the refs before each update
onBeforeUpdate(() => {
divs.value = []
})
return {
list,
divs
}
}
}
</script>
```
## 📍 Watching Template Refs
template ref의 변화를 watching하는 것이 라이프사이클 훅을 사용하는 것의 대안이 될 수 있다.
라이프사이클 훅을 사용하는 것과는 다른 중요한 한가지는 **`watch()` 와 `watchEffect()` 는 DOM이 mount되기 전이나 update 되기 *전에* 실행**된다.
따라서 template ref는 watcher가 실행될 시점에 업데이트 되지 않는다.
## 출처
- [Template Refs - vue3](https://v3.vuejs.org/guide/composition-api-template-refs.html#usage-with-jsx)