재사용성이란 말 그대로 임의의 장소에 저장한 무언가를 여기저기에서 끌어다 쓸 수 있는 패턴 또는 행동을 의미한다. 여기서 무언가란 상태(정적인 데이터 값)일 수 있고, 함수(메소드_상태를 변경하는)일 수도 있다.
플러그인은 일반적으로 Vue에 앱 레벨 기능을 추가하는 자체 코드입니다. 플러그인을 설치하는 방법은 다음과 같습니다.
앱 레벨이란 최상위를 의미한다. 하나의 웹 서비스가 여러가지 컴포넌트들로 이루어져있을 때, 최상단의 컴포넌트를 의미한다.
이 최상단에 기능을 추가한다면 하위의 컴포넌트에서도 사용가능하다를 의미하므로, 재사용성과 밀접한 관련이 있다. 여러강의를 기웃해본 개발자라면 아무렇지 않게도 우리는 이러한 기능을 쓰고있다.(대표적으로 vue-router)
import { createApp } from 'vue';
import App from './App.vue';
import router from '@/router';
const app = createApp(App);
app.use(router);
app.mount('#app');
app.use()
: use라는 메소드를 통해 플러그인을 사용하고 있는 코드이다.
이는 곧 '최상단의 앱에서, 라우터라는 무언가를 계속 끌어다 쓰겠다'와 동일한 의미로 보여진다.
이처럼 라이브러리를 끌어다 쓰는것 말고도, 직접 만든 플러그인을 사용할 수 있다. 그렇다면, 어떻게 커스텀 플러그인을 사용하는지 알아보자.
플러그인은 install() 메서드를 노출하는 객체 또는 단순히 install 함수 자체로 작동하는 함수로 정의됩니다. install 함수는 app.use()에 전달된 추가 옵션과 함께 앱 인스턴스를 받습니다(있는 경우)
공식문서에서는 이러한 커스텀 플러그인을 install()
메소드를 가진 객체로 만들거나, 단순히 함수로 만들 수 있다고 말한다. (가능하면 객체나 함수 중 하나로 통일해서 쓰라고 vue에서는 경고로 알려준다)
언제나 그렇듯 플러그인을 몰아줄 디렉토리를 만들고 스크립트 파일들을 만들어 주면 된다. 아래는 스크립트 파일의 예제이다.
// object example
const objPlugins = {
// install이라는 메소드를 가진 객체 생성
// 최상단의 app과 options를 인자로 받아올 수 있다
install(app, options) {
const objTest = {
foo: 'bar',
};
app.config.globalProperties.$objTest = objTest;
console.log('objPlugins app: ', app);
console.log('objPlugins options: ', options);
// app.component() 전역 컴포넌트
// app.config.globalProperties 전역 애플리케이션 인스턴스에 속성 추가
// app.directive 커스텀 디렉티브
// app.provide() 리소스
app.provide('objTest', objTest);
},
};
// function example
function funcPlugins(app, options) {
console.log('funcPlugins', app, options);
}
export default funcPlugins;
// 플러그인 몰아져있는 디렉토리에서 끌어와서,
import funcPlugins from './plugins/func';
import objPlugins from './plugins/obj';
const app = createApp(App);
// use메소드를 사용해서 쓴다
app.use(funcPlugins(app, { name: 'func jayss' }));
app.use(objPlugins, { name: 'obj jayss' });
option api
에서는 created
사이클 이후부터 라이플 사이클 훅 내부에서 사용(접근) 가능하다.
scrip setup
내에서 쓰려면 플러그인에서 provide
를 사용하여 주입하고, 컴포넌트에서 inject
를 사용해서 써야한다
<script setup>
const objTest = inject('objTest');
console.log('objTest.foo: ', objTest.foo);
</script>
// global-component
import AppAlert from '@/components/app/AppAlert.vue';
import AppCard from '@/components/app/AppCard.vue';
import AppGrid from '@/components/app/AppGrid.vue';
import AppModal from '@/components/app/AppModal.vue';
import AppPagination from '@/components/app/AppPagination.vue';
export default {
install(app) {
app.component('AppAlert', AppAlert);
app.component('AppCard', AppCard);
app.component('AppGrid', AppGrid);
app.component('AppModal', AppModal);
app.component('AppPagination', AppPagination);
},
};
// main.js
import globalComponents from '@/plugins/global-components';
app.use(globalComponents);
전역 컴포넌트로 등록을 해두면, 기존에 import로 컴포넌트를 등록해서 사용하지 않고 바로 컴포넌트로 사용해도 된다.
코어에 포함된 기본 디렉티브 세트(예: v-model 또는 v-show) 외에도 Vue를 사용하면 커스텀 디렉티브를 정의할 수 있습니다.
공식문서에 의하면, 우리가 template
부분에서 사용하던 뷰의 디렉티브 기능을 커스텀하게 제작해서도 쓸 수 있다고 한다.
그렇다면 언제 사용해야할까?
우리는 Vue에서 컴포넌트 기초와 컴포저블이라는 두 가지 형태의 코드 재사용을 도입했습니다. 컴포넌트는 주요 빌딩 블럭(building-block)이고, 컴포저블은 상태 저장 로직을 재사용하는 데 중점을 둡니다. 반면에 커스텀 디렉티브는 주로 일반 엘리먼트에 대한 저수준(low-level) DOM 접근과 관련된 로직을 재사용하기 위한 것입니다.
DOM접근과 관련된 기능을 재사용하고 싶다면 커스텀 디렉티브를 이용하면 되는 것으로 보인다.
// src/directives/focus.js
const focus = {
mounted(el) {
el.focus();
},
};
export default focus;
// src/directives/color.js
function color(el, binding) {
el.style.color = binding.value;
}
export default color;
// src/plugins/global-directives.js
import focus from '@/directives/focus';
import color from '@/directives/color';
export default {
install(app) {
app.directive('focus', focus);
app.directive('color', color);
},
};
// main.js
import globalDirectives from './plugins/global-directives';
app.use(globalDirectives);
커스텀 디렉티브에서 el(첫번째 인자 값)은 DOM요소를 의미한다.
결국은 전역적으로 상태, UI(component), 로직 등을 저장해두고 어떤 컴포넌트에서든 접근하고 사용할 수 있도록 등록을 해주는 행위이다. 반드시 재사용이 필요한 부분에서만 이를 활용하는 것이 바람직해 보인다.