cover

DOM에 접근할 때 보통 querySelector나 getElementById 등을 사용합니다. Vue에서는 이를 더 간편하게 사용할 수 있도록 ref라는 속성을 제공합니다. 이를 어떻게 사용하는지 자세히 알아보겠습니다.


Javascript DOM 접근 방법

Javascript에서는 접근할 태그에 class나 id를 넣었었습니다.

html
      <input id="my-input" />
<script>
	const myInput = document.querySelector("#my-input");
	myInput.value = "Hello";
</script>
    

Vue의 DOM 접근 방법 (ref)

Vue에서도 동일하게 할 수 있지만, ref 라는 특수한 속성을 사용하면 더 쉽게 접근할 수 있습니다.

html
      <script>
export default {
  mounted() {
    this.$refs['my-input'].value = "Hello"
  }
}
</script>

<template>
  <input ref="my-input" />
</template>
    

ref 속성이 들어간 태그들은 컴포넌트의 $refs 값으로 접근할 수 있게 됩니다.

warn
      주의할 점은 해당 태그가 마운트가 되었을 때(mounted) 사용해야합니다. 마운트되지 않으면 당연히 해당 태그가 없으니 접근할 수가 없겠죠. 그래서 $refs 안은 빈 객체가 들어 있게되고, $refs[’my-input’]는 undefined가 됩니다.
    

v-for와 같이 사용하는 경우

만약 v-for를 사용하는 곳에 ref를 넣으면 배열로 받게 됩니다.

html
      <template>
  <ul>
    <li v-for="item in list" ref="items">
      {{ item }}
    </li>
  </ul>
</template>

<script>
export default {
  data() {
    return {
      list: [
        /* ... */
      ]
    }
  },
  mounted() {
    console.log(this.$refs.items)
  }
}
</script>
    

콘솔 창을 보면 다음과 같이 들어있음을 볼 수 있습니다.

image
warn
      공식 사이트에 따르면 이 ref 배열의 순서는 list의 배열과 동일한 순서가 아닐 수도 있다고 합니다.
    

함수 (Function) Refs

mounted에서 처리하는 것 대신에 ref에 함수를 넣어서 처리하는 방법도 있습니다. ref에 넣는 함수는 해당 태그를 매개변수로 받습니다.

html
      <template>
  <div id="app">
    <input :ref="(el) => funcRef(el, n)" v-for="n of 3" />
  </div>
</template>

<script>
export default {
  methods: {
    funcRef(el, index) {
      el.value = index;
    }
  }
};
</script>
    
image

컴포넌트가 업데이트될 때마다 이 함수를 실행합니다. 만약 이 태그가 unmount된다면 함수가 받는 태그값은 null이 됩니다.

컴포넌트 Refs

컴포넌트에 ref를 사용할 수도 있는데요. 이 경우 해당 태그가 아닌 컴포넌트가 ref에 들어갑니다.

html
      <script>
import Child from './Child.vue'

export default {
  components: {
    Child
  },
  mounted() {
    console.log(this.$refs.child);
  }
}
</script>

<template>
  <Child ref="child" />
</template>
    

Child 인스턴스가 가진 data, computed, methods 들 모두 접근이 가능합니다. 물론 마운트가 된 이후에만 가능합니다.

expose

ref를 사용하면 자식 컴포넌트의 모든 것을 접근할 수 있지만 이를 제한할 수도 있습니다. expose를 이용해서 말이죠.

javascript
      export default {
  expose: ['publicData', 'publicMethod'],
  data() {
    return {
      publicData: 'foo',
      privateData: 'bar'
    }
  },
  methods: {
    publicMethod() {
      /* ... */
    },
    privateMethod() {
      /* ... */
    }
  }
}
    

expose로 이 컴포넌트에 접근할 수 있는 것들을 정할 수 있습니다.

외부에서 사용할 수 있는 것들
publicData
publicMethod
외부에서 사용할 수 없는 것들
privateData
privateMethod