특정 기능을 하는 코드를 유연하게 사용할 수 있도록 하는 기능.

믹스인은 내가 사용하지도 않는 메서드도 같이 컴포넌트에 들어가 중복되거나 불필요한 부담이 많았었다.

더하기 계산기를 만드는 코드를 composition api를 통해 바꿔보자.

<template>
  <div>
    <h2>Calculator</h2>
    <div>
      <input type="text" v-model.**number**="**num1**" @**keyup**="**plusNumbers**" />
      <span> + </span>
      <input type="text" v-model.**number**="**num2**" @keyup="plusNumbers" />
      <span> = </span>
      <span>{{**result**}}</span>
    </div>
  </div>
	<!-- **keyup** event : 키보드에서 손을 떼면 발생하는 이벤트 -->
</template>

<script>
  export default {
    name: 'CalculatorView',
    data() {
      return {
        num1: 0,
        num2: 0,
        result: 0
      }
    },
    methods: {
      **plusNumbers**() {
        this.result = this.num1 + this.num2
      }
    }
  }
</script>

setup()

composition api에는 data()가 없는 대신 setup() 옵션이 존재한다. setup() 안에서 한꺼번에 변수나 메서드들을 선언 후 반환해서 사용할 수 있다.

setup은 composition api 작업을 진행하는 위치를 이야기한다. 컴포넌트가 생성되기 전에, props가 resolve될 때 실행된다. 따라서 setup 안에 this가 존재하지않

vue 안의 reactive api를 통해서 반응형으로 데이터들을 적용할 수 있다. reactive로 선언된

<template>
  <div>
    <h2>Calculator</h2>
    <div>
      <input type="text" v-model.number="state.num1" @keyup="plusNumbers" />
      <span> + </span>
      <input type="text" v-model.number="state.num2" @keyup="plusNumbers" />
      <span> = </span>
      <span>{{ result }}</span>
    </div>
  </div>
</template>

<script>
import {reactive} from 'vue'

export default {
  name: 'CalculatorView',
  setup() {
    let state = reactive({
			// **reactive를 사용해서 num1, num2, result를 실시간 변경 사항에 반응형으로 적용한다.**  
      num1: 0,
      num2: 0,
      result: 0,
    })

    function plusNumbers() {
      this.result = this.num1 + this.num2
    }

    return {
      // **reactive로 선언된 state와 plusNumbers 함수를 반환함으로써** 
			// **기존 data, methods 옵션처럼 사용할 수 있다.**
      state,
      plusNumbers
    }
  },
}
</script>

function 대신 state 안의 reactive 변수에서 computed 사용하기

keyup 이벤트와 plusNumbers() 함수를 사용하지 않고 computed를 사용한다.

<template>
  <div>
    <h2>Calculator</h2>
    <div>
      <input type="text" v-model.number="state.num1"/>
      <span> + </span>
      <input type="text" v-model.number="state.num2"/>
      <span> = </span>
      <span>{{ state.result }}</span>
    </div>
  </div>
</template>

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

export default {
  name: 'CalculatorView',
  setup() {
    let state = reactive({
      num1: 0,
      num2: 0,
      result: computed(() => state.num1 + state.num2),
    })

    return {
      state,
    }
  },
}
</script>

기존에 우리가 했던 방식인 options API는 prop, data, computed, hook 등의 옵션의 규칙을 지켜서 작성해야 한다. 그러다 보니 같은 기능을 하는 코드들이 띄엄띄엄 존재한다. 그래서 코드 전체를 이해하고 추적하기가 쉽지 않다. 이에 반해 Composition API는 연관성 있는 코드들끼리 같은 위치에 모아놓을 수 있다는 장점이 있다.

toRefs를 사용한 외부 function 사용

<template>
  <div>
    <h2>Calculator</h2>
    <div>
      <input type="text" v-model.number="num1"/>
      <span> + </span>
      <input type="text" v-model.number="num2"/>
      <span> = </span>
      <span>{{ result }}</span>
    </div>
  </div>
</template>

<script>
import {reactive, computed, toRefs} from 'vue'

function plusCalculator() {
  let state = reactive({
    num1: 0,
    num2: 0,
    result: computed(() => state.num1 + state.num2)
  })

  return **toRefs**(state) // 반응형으로 선언된 num1, num2, result가 외부 function에서 제대로 사용되기 위해서
}

export default {
  name: 'CalculatorView',
  setup() {
    let { num1, num2, result } = **plusCalculator**()  // 외부 function

    return {
      num1,
      num2,
      result
    }
  },
}
</script>

왜 이렇게 외부 function을 따로 빼서 사용하는 걸까?

→ 공통 함수를 이용하기 위해서!