캡틴판교 로고

Vue 3 Composition

Table of Contents

setup

export default {
  components: {
    // ...
  },
  setup() {
    var a = 10;

    return {
      a
    }
  },
  methods: {
    logText() {
      console.log(this.a); // 10
    }
  }
}
<template>
  <div>
    <!-- 
      뒤에 나오는 `reactive`, `ref` 속성이 적용되었다고 가정하고 
      아래 값이 10이 될 것이라고 먼저 쉽게 생각하자.
    -->
    <p></p>
  </div>
</template>
export default {
  setup() {
    var a = ref(10);
    console.log(a); // { value: 10 }

    return {
      a
    }
  },
}

ref는 Reactive Reference의 준말입니다

setup의 인자들

setup 함수의 인자로 propscontext가 있습니다.

props

프롭스는 아래와 같이 컴포넌트(인스턴스) 옵션 속성에 정의한 뒤 setup 함수의 첫 번째 인자로 접근합니다.

export default {
  props: {
    items: Array
  },
  setup(props) {
    console.log(props.items);
  }
}

setup 함수의 인자로 넘어온 props에는 ES6 디스트럭처링을 사용하면 안됩니다. props의 반응성이 깨질 수도 있기 때문이죠. 대신 아래와 같은 문법으로 디스트럭처링을 할 수 있습니다.

import { toRefs } from 'vue'

export default {
  props: {
    items: Array
  },
  setup(props) {
    const { items } = toRefs(props);
  }
}

context

컨텍스트는 컴포넌트 속성 3개를 접근할 수 있는 인자입니다.

export default {
  setup(props, context) {
    // 애트리뷰트(반응성 없는 객체)
    console.log(context.attrs)

    // 슬롯(반응성 없는 객체)
    console.log(context.slots)

    // 이벤트 에밋
    console.log(context.emit)
  }
}

컨텍스트의 3가지 속성에는 모두 반응성이 없으므로 아래와 같이 디스트럭처링 해서 사용합니다.

export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}

setup 안에서 접근 가능한 컴포넌트 속성들

setup 함수가 실행됐을 때는 아직 컴포넌트가 생성된 것이 아니기 때문에 위에서 살펴봤던 4가지 속성만 접근할 수 있습니다.

setup 함수 바깥에 정의된 아래 속성들은 setup 함수 안에서 접근할 수 없습니다.

setup의 반환 값

setup 함수에서 반환한 객체는 템플릿 표현식에서 사용할 수 있습니다.

<template>
  <div>
    <p></p> <!-- counter.value로 접근하지 않아도 라이브러리 내부적으로 화면에 value 값을 엮어줍니다 -->
    <p></p>
  </div>
</template>

<script>
import { ref, reactive } from 'vue'

export default {
  setup() {
    const counter = ref(0);
    counter.value++; // 1
    const book = reactive({ title: 'Vue 3 Guide' });

    return {
      counter,
      book
    }
  }
}
</script>

template refs

Vue 3에서 가장 유의해야 할 문법입니다. 뷰 이전 버전을 사용하셨던 분들은 익숙해진 습관 때문에라도 컴포지션에서의 ref 문법을 좀 유심히 살펴봐야 할 필요가 있습니다. 이전까지는 ref 속성을 아래와 같이 접근했었습니다.

<template>
  <button ref="myButton">click me</button>
</template>

<script>
export default {
  mounted() {
    console.log(this.$refs.myButton); // <button>click me</button>
  }
}
</script>

컴포지션 API에서 템플릿 표현식의 ref를 접근할 때는 아래의 문법을 활용합니다.

<template>
  <button ref="myButton">click me</button>
</template>

<script>
import { ref, onMounted } from 'vue'

export default {
  setup() {
    const myButton = ref(null)

    onMounted(() => {
      // the DOM element will be assigned to the ref after initial render
      console.log(myButton.value) // <button>click me</button>
    })

    return {
      myButton
    }
  }
}
</script>

위 코드에서 알 수 있는 점은 템플릿 표현식의 ref도 여태까지 살펴봤었던 ref() API와 동일한 속성으로 취급된다는 것입니다.