Vue 컴포넌트에서 로직 재사용하기
업데이트: Link
Vue 컴포넌트에서 로직 재사용하기
Reusing Logic in Vue Components Written by Alex Jover Morales
어느 날 Vue 애플리케이션을 만들기 시작합니다. 애플리케이션의 다른 부분을 구성하기 위해 컴포넌트를 만들기 시작합니다. 멋지네요. Vue와 웹 컴포넌트 아키텍처의 훌륭한 개발 경험을 느낄 수 있을 것입니다. 프로젝트를 진행하면서 아마도 페이지와 컴포넌트별로 응용 프로그램 컴포넌트를 구조화하기 시작합니다.
그러나 프로젝트가 계속 성장함에 따라 여러 컴포넌트에서 반복된다는 사실을 알기 시작합니다. Don’t Repeat Yourself(Dry) 및 Keep It Simple, Stupid(KISS)에 대해 들어왔습니다. 사용과 유지관리가 쉬운 소프트웨어를 작성할 수 있는 두 가지 원칙입니다.
이러한 원칙을 따르는 데 도움이 되는 몇 가지 패턴, 라이브러리 및 기술을 이미 알고 있을 수도 있습니다. Vuex는 컴포넌트에서 상태 논리를 가져오는 데 도움이 되며 Vue 라우터는 라우팅 논리에 대해 동일한 작업을 수행하지만 컴포넌트는 어떻습니까?
컴포넌트에 속한 일부 UI 기능을 재사용해야 하는 경우가 종종 있습니다. 예를 들어, Popover와 Tooltip은 특정 이벤트가 트리거될 때 열고 닫는 기능을 공유할 수 있을 뿐만 아니라 요소에 고정되고 배치됩니다.
이 기사에서는 스크롤 이벤트를 수신하고 스크롤 위치에 따라 색상을 변경하는 Colorful.vue 컴포넌트의 예를 사용할 것입니다. 창 높이보다 높으면 파란색, 그렇지 않으면 빨간색이 됩니다. 이는 :style
을 사용하여 color
로컬 상태 변수를 바인딩하여 달성됩니다.
<!-- Colorful.vue -->
<template>
<div :style="{ background: color }">
</div>
</template>
<script>
export default {
data: () => ({
color: "red"
}),
methods: {
handleScrollChange(status) {
this.color = status === "in" ? "red" : "blue";
},
handleScroll() {
if (window.scrollY > window.innerHeight) {
this.handleScrollChange("out");
} else {
this.handleScrollChange("in");
}
}
},
mounted() {
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
}
};
</script>
컴포넌트에 잘못된 것이 없을 수도 있습니다. mounted
후크에 scroll
이벤트를 등록하고 destroyed
에 등록을 취소합니다. 스크롤 위치 확인을 수행하는 handleScroll
메소드를 호출하고 status
인수에 따라 색상을 변경하기 위해 handleScrollChange
메소드를 호출합니다.
현재 스크롤 기능은 Colorful
구성요소 안에 있습니다. 그러나 mounted
및 destroyed
후크와 handleScroll
메서드를 제거하여 다른 컴포넌트에서 재사용할 수 있습니다.
이를 수행하는 다양한 방법을 살펴보겠습니다.
Component 상속
먼저 스크롤 관련 동작을 자체 컴포넌트 Scroll.js로 이동하여 시작하겠습니다.
export default {
methods: {
handleScroll() {
if (window.scrollY > window.innerHeight) {
this.handleScrollChange("out");
} else {
this.handleScrollChange("in");
}
}
},
mounted() {
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
}
};
보시다시피 이 Scroll 컴포넌트는 handleScrollChange
가 존재하기를 기대합니다. 이 컴포넌트는 자식 컴포넌트에서 구현합니다. 즉, 이 컴포넌트는 확장되어야 하며 자체적으로 작동할 수 없습니다.
JavaScript만 포함하기 때문에 .js 파일에 작성할 수 있지만 필요한 경우 .vue 파일도 될 수 있습니다. .vue 파일의 JavaScript 부분만 상속된다는 점에 유의하십시오.
그런 다음 Colorful 컴포넌트에서 이동한 컴포넌트 동작을 모두 제거하고 extens
컴포넌트 옵션을 사용하여 Scroll 파일을 가져옵니다.
<!-- Colorful.vue -->
<template>
<div :style="{ background: color }"></div>
</template>
<script>
import Scroll from "./scroll";
export default {
extends: Scroll,
data: () => ({
color: "red"
}),
methods: {
handleScrollChange(status) {
this.color = status === "in" ? "red" : "blue";
}
}
};
</script>
컴포넌트 확장은 클래스 상속이 아니라는 점에 유의하십시오. 이 경우 Vue는 부모 및 자식 컴포넌트 옵션을 모두 병합하여 새로운 혼합 개체를 만듭니다.
예를 들어, 이전 예제에서는 다음 API를 사용하는 컴포넌트를 갖게 됩니다.
{
data: () => ({
color: "red"
}),
methods: {
handleScrollChange(status),
handleScroll,
},
mounted,
destroyed
}
mounted
및 destroyed
후크의 경우 부모와 자식 모두 유지되며 부모에서 자식으로 상속 순서대로 호출됩니다.
Mixins
컴포넌트 상속과 유사하게 컴포넌트 논리를 공유하기 위해 믹스인을 사용할 수 있습니다. 그러나 이전 예제에서는 하나의 컴포넌트에서만 상속할 수 있지만 믹스인을 사용하면 여러 컴포넌트의 기능을 결합할 수 있습니다.
사실 이전 예제의 Scroll.js 파일에서 아무것도 변경할 필요가 없습니다. Colorful 컴포넌트에서 extends
대신 mixins
옵션을 사용하는 것으로 충분합니다. mixins
는 배열을 예상한다는 점을 기억하세요.
<!-- Colorful.vue -->
<script>
import Scroll from "./scroll";
export default {
mixins: [Scroll],
data: () => ({
color: "red"
}),
methods: {
handleScrollChange(status) {
this.color = status === "in" ? "red" : "blue";
}
}
};
</script>
컴포넌트 상속과의 주요 차이점은 순서가 다르다는 것입니다. 컴포넌트 상속에서는 자식의 후크가 부모보다 먼저 실행되고 믹스인에서는 컴포넌트가 사용하기 전에 후크가 실행됩니다.
또한 믹스인은 템플릿이나 스타일 태그를 가질 수 없으며 그냥 평범한 JavaScript입니다.
재사용 가능한 Component 작성
상속과 믹스인은 구현하기 쉬운 것처럼 보이지만 어떻게든 암시적입니다. 앞의 예에서 Scroll을 사용할 때 handleScrollChange
메소드를 구현해야 한다는 것을 알아야 합니다.
이 경우는 그렇게 나쁘지는 않지만 여러 믹스인을 확장하거나 사용할 때 상황이 혼란스러워지기 시작하고 많은 부분에서 기능을 추적하기 시작할 수 있습니다.
기능을 재사용하는 또 다른 방법은 props를 수신하고 이벤트를 내보내는 재사용 가능한 컴포넌트를 만드는 것입니다. 이렇게 하면 마법 병합도 없고 컨텍스트를 공유하지도 않는 보다 명시적인 솔루션이 됩니다. 또한 이 솔루션은 다른 컴포넌트 기반 기술에도 동일한 접근 방식을 적용할 수 있으므로 보다 “보편적” 입니다.
먼저 Scroll을 .vue 컴포넌트로 만들어야 합니다.
<!-- Scroll.vue -->
<template>
<div></div>
</template>
<script>
export default {
methods: {
handleScroll() {
if (window.scrollY > window.innerHeight) {
this.$emit("scrollChange", "out");
} else {
this.$emit("scrollChange", "in");
}
}
},
mounted() {
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
window.removeEventListener("scroll", this.handleScroll);
}
};
</script>
이 경우, 매직 메소드 handleScrollChange
를 호출하는 대신 상위 컴포넌트가 작업을 수행하는 데 사용할 수 있는 scrollChange
이벤트를 방출합니다.
그런 다음 Colorful.vue에서 컴포넌트로 가져와서 scrollChange
이벤트를 처리해야 합니다.
<!-- Colorful.vue -->
<template>
<scroll
@scrollChange="handleScrollChange"
:style="{ background: color }">
</scroll>
</template>
<script>
import Scroll from "./scroll";
export default {
components: {
Scroll
},
data: () => ({
color: "red"
}),
methods: {
handleScrollChange(status) {
this.color = status === "in" ? "red" : "blue";
}
}
};
</script>
div
태그를 scroll
로 교체했지만 Colorful 컴포넌트 로직은 그대로 유지됩니다.
마무리
스크롤 기능을 제거하고 재사용하는 세 가지 방법을 보았습니다. 귀하의 경우에 따라 하나 또는 다른 것을 사용할 것입니다.
컴포넌트 상속 및 믹스인은 컴포넌트 논리의 일부를 마술처럼 분리하고 함께 병합하는 방법을 제공합니다. 이는 너무 혼동되지 않는 한 어떤 경우에 적합할 수 있습니다. 특히 Mixin은 여러 개를 결합할 수 있으므로 더 강력합니다.
컴포넌트 구성을 사용하는 것이 더 명확하고 명확한 솔루션입니다. 다른 컴포넌트 기반 프레임워크에서도 동일한 기술을 사용할 수 있습니다. 그러나 어떤 경우에는 mixin만큼 편리하지 않을 수 있습니다.
Codesandbox에서 데모를 볼 수 있습니다. 여기서 index.js 파일의 예제
를 변경하여 세 가지를 시도할 수 있습니다.
댓글남기기