Today I Learned ... Vue.js
🙋♂️ Reference Book
DAY 04 - 220603
-9. Composition API
-10. Proxy 사용
컴포넌트 내에서 사용하는 특정 기능을 갖는 코드를 유연하게 구성하여 사용하게 하는
함수 기반 API.
-> Vue 3 버전의 핵심 기능임.
Setup
이라는 메서드 내에서 한덩어리로 코드를 구현할 수 있음.❗️ Vue 2에서는 mixin(믹스인)을 통해 코드를 재사용했지만, 오버라이딩 문제 등으로 관리가 어려웠음.
📝 예제 - 사용자로부터 숫자 두개를 입력받고, 둘을 더한 값을 출력하는 코드.
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="number" v-model="num1" @keyup="plusNumbers" />
<span> + </span>
<input type="number" v-model="num2" @keyup="plusNumbers" />
<span> = </span>
<span>{{ result }}</span>
</div>
</div>
</template>
<script>
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'calculator',
data() {
return {
num1: 0,
num2: 0,
result: 0,
};
},
methods: {
plusNumbers() {
this.result = this.num1 + this.num2;
},
},
};
</script>
-> keyup 이벤트가 발생할 때 마다 두 수를 더하여 result 값을 반환함.
컴포지션 ver.
위와 동일한 기능을 하는 코드를 컴포지션 API를 이용하여 구현하면
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="number" v-model="state.num1" @keyup="plusNumbers" />
<span> + </span>
<input type="number" v-model="state.num2" @keyup="plusNumbers" />
<span> = </span>
<span>{{ state.result }}</span>
</div>
</div>
</template>
<script>
import { reactive } from 'vue';
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'calculator',
setup() {
let state = reactive({
num1: 0,
num2: 0,
result: 0,
});
function plusNumbers() {
state.result = state.num1 + state.num2;
}
return {
state,
plusNumbers,
};
},
};
</script>
import { reactive } from 'vue';
vue의 reactive를 임포트해서 실시간 변경사항에 대한 반응형 적용.
setup 내에서 let state = reactive({});
와
function plusNumbers(){}
로 선언함.
state, plusNumbers를 반환함으로써
기존에 data, methods 옵션 처럼 템플릿에서 사용 가능하도록 함.
import { reactive, computed } from 'vue'; // 👈 computed 임포트
...
setup() {
let state = reactive({
num1: 0,
num2: 0,
result: computed(() => state.num1 + state.num2), // num1, num2 변경시 즉시 더한 값을 result로 반환
});
return {
state,
};
},
computed: {
fullName() {
return this.firstName + this.lastName;
}
}
🔺 기존 computed 옵션 사용법
🔻 setup 내에서 사용시 (컴포지션 API)
// setup 내에서 사용시
fullName: computed(() => state.firstName + state.lastName)
<template>
<div>
<h2>Calculator</h2>
<div>
<input type="number" v-model="num1" />
<span> + </span>
<input type="number" v-model="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가 정상 동작하게 해줌
}
export default {
// eslint-disable-next-line vue/multi-word-component-names
name: 'calculator',
setup() {
let { num1, num2, result } = plusCalculator();
return {
num1,
num2,
result,
};
},
};
</script>
컴포지션 API 내에서 사용할 수 있는 라이프사이클 훅.
created / beforeMount / mounted / beforeUpdate / updated / beforeUnmount unmounted 등
setup() -> beforeCreate와 created 사이에서 실행됨.
부모 컴포넌트
<template>
<CompositionInject />
</template>
<script>
import { provide } from '@vue';
import CompositionInject from './CompositionInject';
export default {
components: {
CompositionInject,
},
setup() {
provide('title', 'Vue.js 프로젝트'); // provide 함수 : key-value 쌍으로 전달할 값 설정
},
};
</script>
자식 컴포넌트
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { inject } from 'vue';
export default {
setup() {
const title = inject('title'); // key값으로 가져옴
return { title };
},
};
</script>
자주 사용되는 기능을 메서드로 만들어 등록해놓고, 모듈을 import 하듯이
Vue에서도 mixin을 통해 가능함.
믹스인 이란?
- 기능은 따로 구현하고, 필요할 때 마다 믹스이 파일을 컴포넌트에 결합하여 사용하는 방법.
예제 - Mock 서버의 API를 호출하는 믹스인.
src/api.js 생성
import axios from 'axios';
export default {
methods: {
async $callAPI(url, method, data) {
return (
await axios({
method: method,
url,
data,
}).catch((e) => {
console.log(e);
})
).data;
},
},
};
views/Mixins.vue 생성
<script>
import ApiMixin from '../api.js';
export default {
mixins: [ApiMixin],
data() {
return {
personList: [],
};
},
async mounted() {
this.personList = await this.$callAPI(
'https://5604e27b-c8b9-48b0-98a9-c4a272c9456b.mock.pstmn.io/list',
'get'
);
console.log(this.personList);
},
};
</script>
위와 같이 mounted 같은 라이프사이클 훅을 async-awiat으로 작성 가능함.
-> axios.get은 비동기이므로
Mixin에서 methods로 등록한 함수를 this.$callAPI와 같이 사용 가능함.