[Vue] 8. Vue 컴포넌트 재활용 & 공통 함수 개발 - 1) 믹스인(Mixins)
믹스인(Mixins)
믹스인(Mixins)은 vue 프로젝트 내에서 공통 함수를 만들 수 있게 해주는 기능이다.
우리가 저번에 ServerData.vue 파일에서 mock 서버에 있는 데이터를 호출해서 이용하는 코드를 짠 적이 있는데 그때 api라는 함수를 만들어서 사용했었다. 그런데 이 함수는 이 화면에서만 필요한 게 아니고 거의 모든 화면에서 이 함수를 사용한다. 그래서 이 함수를 공통 함수로 만들어서 사용하려고 한다. 이때, 믹스인(Mixins)를 활용해서 해보려고 한다.
mixin 사용하기
// ServerData.vue
async api(url, method, data) {
return (
await axios({
method: method,
url: url,
data: data,
}).catch((e) => {
console.log(e);
})
).data;
},
main.js와 같은 경로에 api.js 파일을 생성해준다.
그리고 api 함수를 여기에 정의해준다. 이름은 $callAPI로 바꿔준다. 함수 이름 앞에 $ 기호를 붙이는 이유는 이 함수를 컴포넌트에서 사용할 때 그 컴포넌트에 존재하는 함수와 이름이 겹칠 수도 있기 때문이다. mixin에서 callAPI라는 함수를 가져와서 사용하는데 그 컴포넌트에도 callAPI라는 함수가 있으면 함수 오버라이딩이 일어나서 문제가 생긴다. 그래서 이름 충돌을 방지하기 위해 특이한 prefix를 붙여주는 것이다.
// api.js
import axios from "axios";
export default {
methods: {
async $callAPI(url, method, data) {
return (
await axios({
method: method,
url: url,
data: data,
}).catch((e) => {
console.log(e);
})
).data;
},
},
};
views 폴더에 MixinTest.vue 파일을 만들어준다.
api.js를 import 해준다.
import ApiMixin from "../api.js";
mixins에 ApiMixin을 추가해준다. 이렇게 하면 api.js에 정의한 함수 코드가 그대로 이 컴포넌트에 복사돼서 들어가게 된다.
export default { mixins: [ApiMixin], };
// MixinTest.vue
<template>
<div>
<button type="button" @click="getProductList">조회</button>
<table>
<thead>
<tr>
<th>제품명</th>
<th>가격</th>
<th>카테고리</th>
<th>배송료</th>
</tr>
</thead>
<tbody>
<tr :key="i" v-for="(product, i) in productList">
<td>{{ product.product_name }}</td>
<td>{{ product.price }}</td>
<td>{{ product.category }}</td>
<td>{{ product.delivery_price }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import ApiMixin from "../api.js";
export default {
mixins: [ApiMixin],
components: {},
data() {
return {
productList: [],
};
},
setup() {},
created() {},
mounted() {},
unmounted() {},
methods: {
async getProductList() {
this.productList = await this.$callAPI(
"https://a1e284c5-db6b-4726-a0be-a72a59f81862.mock.pstmn.io/productList",
"get",
{}
);
console.log(this.productList);
},
},
};
</script>
<style scoped></style>
routes에 등록해준다.
// index.js
const routes = [
...,
{
path: "/mixin",
name: "MixinTest",
component: () =>
import(/* webpackChunkName: "about" */ "../views/MixinTest.vue"),
},
];
ServeData.vue에서 만들었던 결과와 똑같이 나오는 것을 확인할 수 있다.
mixin mounted와 component mounted의 순서
mixin 함수를 정의하는 파일에서 mounted하는 것과 component에서 mounted하는 것의 순서가 어떻게 되는지 알아보자.
api.js의 mounted에 console 창에 프린트하는 코드를 넣어준다.
// api.js
import axios from "axios";
export default {
mounted() {
console.log("믹스인 mounted");
},
methods: {
async $callAPI(url, method, data) {
return (
await axios({
method: method,
url: url,
data: data,
}).catch((e) => {
console.log(e);
})
).data;
},
},
};
MixinTest.vue의 mounted에도 console창에 프린트하는 코드를 넣어준다.
// MixinTest.vue
export default {
..., // 이전 코드 생략
mounted() {
console.log("컴포넌트 mounted");
},
};
mixin에 있는 mounted 코드가 먼저 실행되고 그 다음에 component에 있는 mounted 코드가 실행되는 것을 볼 수 있다.
lifecycle을 이용하는 함수를 mixin을 사용해서 만들기
vue lifecycle은 다음과 같다. 사용자가 그 컴포넌트에 머무르는 시간을 측정하는 함수를 만들려고 한다. 그럼 mounted에서 시간을 측정하고 unmounted에서 시간을 측정해서 빼주면 사용자가 컴포넌트에 머무르는 시간을 측정할 수 있다. 그런데 이 코드를 모든 컴포넌트마다 짜기는 불편하다. 그래서 mixin을 사용해서 만들어보려고 한다.
monitoring.js 파일을 main.js와 같은 경로에 생성하고 머무르는 시간을 계산하는 코드를 작성했다고 가정하자.
// monitoring.js
export default {
mounted() {
// 데이터베이스에 시간 저장
},
unmounted() {
// 데이터베이스에 시간 저장
},
};
MixinTest.vue 파일에 monitoring.js를 import해주고 mixins에 추가해준다.
// MixinTest.vue
<script>
import ApiMixin from "../api.js";
import MonitoringMixin from "../monitoring.js";
export default {
mixins: [ApiMixin, MonitoringMixin],
};
</script>
mixin을 Global로 선언해주기
사실 $callAPI같은 함수는 거의 모든 컴포넌트에서 사용한다. 그런데 이걸 모든 컴포넌트에서 매번 import 해주는 것도 사실 굉장히 귀찮은 일이다. 그런 경우에 이것을 global로 등록해두고 사용할 수 있다.
mixins.js 파일을 main.js와 같은 경로에 만들고 $callAPI 함수를 똑같이 복사해서 넣어준다. 그런데 함수 이름은 $api라고 하자.
// mixins.js
import axios from "axios";
export default {
methods: {
async $api(url, method, data) {
return (
await axios({
method: method,
url: url,
data: data,
}).catch((e) => {
console.log(e);
})
).data;
},
},
};
main.js에 mixins를 import해주고 사용 설정을 해준다.
import mixins from "./mixins";
app.mixin(mixins);
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import mixins from "./mixins";
const app = createApp(App);
app.use(router);
app.mixin(mixins);
app.mount("#app");
그러면 MixinTest.vue에서 import를 하지 않아도 바로 사용할 수가 있다. 기존에 import하는 코드와 mixins에 ApiMixin을 추가해줬던 것을 지우고 다시 실행해보자.
// MixinTest.vue
<template>
<div>
<button type="button" @click="getProductList">조회</button>
<table>
<thead>
<tr>
<th>제품명</th>
<th>가격</th>
<th>카테고리</th>
<th>배송료</th>
</tr>
</thead>
<tbody>
<tr :key="i" v-for="(product, i) in productList">
<td>{{ product.product_name }}</td>
<td>{{ product.price }}</td>
<td>{{ product.category }}</td>
<td>{{ product.delivery_price }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
// import ApiMixin from "../api.js";
import MonitoringMixin from "../monitoring.js";
export default {
mixins: [MonitoringMixin],
components: {},
data() {
return {
productList: [],
};
},
setup() {},
created() {},
mounted() {
console.log("컴포넌트 mounted");
},
unmounted() {},
methods: {
async getProductList() {
this.productList = await this.$api(
"https://a1e284c5-db6b-4726-a0be-a72a59f81862.mock.pstmn.io/productList",
"get",
{}
);
console.log(this.productList);
},
},
};
</script>
<style scoped></style>
똑같이 잘 실행되는 것을 확인할 수 있다.
mixin을 global로 사용할 때 주의할 점
쓸데없는 함수들을 모두 global로 선언해놓으면 컴포넌트에서 그 함수를 실제로 사용하지도 않는데 함수 코드가 모든 컴포넌트에 전부 복사되어서 비효율적으로 될 수 있다. 그러니 거의 모든 컴포넌트에서 사용하는 함수 정도만 global로 선언해놓고 나머지는 그냥 import 해서 사용하는 것을 추천한다.
Author And Source
이 문제에 관하여([Vue] 8. Vue 컴포넌트 재활용 & 공통 함수 개발 - 1) 믹스인(Mixins)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@manyyeon/Vue.js-8.-Vue-컴포넌트-재활용-공통-함수-개발-1-믹스인Mixins저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)