Vue
의 모든 컴포넌트에서 전역적으로 사용할 수 있는 기능을 만들 수 있고, 이를 플러그인이라고 한다.
플러그인은 기본적으로 아래와 같이 작성한다.
export default {
install(app, options) {
app.config.globalProperties.$fetch = (url, fetchOptions) => {
return fetch(url, fetchOptions).then(res => res.json());
};
}
};
위처럼 작성하면 this.$fetch
를 이용해서 해당 플러그인을 사용할 수 있으며, 프로퍼티의 $
는 필수는 아니고, 단지 전역 기능이라는 것을 의미하기 위한 기호다.
플러그인을 작성했다고 바로 사용할 수 있는 것은 아니고, 아래처럼 Vue
어플리케이션 인스턴스의 use
메서드를 이용해서 등록하는 과정을 거쳐야 한다.
import * as Vue from 'vue';
import App from './App.vue';
import fetchPlugin from '~/plugins/fetch';
const app = Vue.createApp(App);
app.use(fetchPlugin);
app.mount('#app');
또한, 플러그인을 등록할 때 use()
메서드의 두 번째 인자로 옵션을 추가할 수 있다.
import * as Vue from 'vue';
import App from './App.vue';
import fetchPlugin from '~/plugins/fetch';
const app = Vue.createApp(App);
app.use(fetchPlugin, {
someOptions...
});
app.mount('#app');
믹스인은 여러 컴포넌트에서 반복적으로 사용하는 로직을 묶어서 재사용할 수 있도록 만드는 기능이다.
만약 믹스인의 내용이 객체 옵션인 경우, 병합을 진행하며 중복되는 값은 컴포넌트의 내용을 우선 적용하게 된다.
하지만 라이프사이클 훅은 믹스인의 훅과 컴포넌트의 훅이 모두 호출된다는 점에 유의하도록 하자.
믹스인은 기본적으로 아래처럼 객체 리터럴로 작성한다.
const Mixin = {
data() {
return {
message: 'mixin Message',
name: 'JaeungE'
}
}
}
작성한 믹스인은 애플리케이션 인스턴스의 mixin()
메서드를 이용해서 전역으로도 등록이 가능하지만, 전역으로 등록하게 되면 원하지 않는 컴포넌트에도 믹스인이 적용되므로 주의하자.
mixin
export default {
data() {
return {
message: 'default Message~',
name: 'JaeungE'
};
}
};
main.js
import * as Vue from 'vue';
import App from './App.vue';
import fetchPlugin from '~/plugins/fetch';
import myMixin from '~/mixins/MyMixin';
const app = Vue.createApp(App);
app.use(fetchPlugin);
app.mixin(myMixin);
app.mount('#app');
이처럼 전역 등록이 아닌, 원하는 컴포넌트에만 믹스인을 적용하고 싶다면 컴포넌트의 mixins
옵션에 배열 리터럴로 원하는 믹스인을 적용하면 된다.
<template>
<Hello />
</template>
<script>
import Hello from '~/components/Hello';
import myMixin from '~/mixins/MyMixin';
export default {
components: {
Hello
},
mixins: [myMixin],
mounted() {
console.log(this.$data);
}
};
</script>
컴포넌트 내부 데이터에는 접근이 가능한 상태로, 다른 엘리먼트에 출력할 수 있도록 만들어주는 기능.
아래는 Modal
을 구현할 때, fixed
의 위치가 변하는 문제를 해결하기 위해서 사용한 예제다.
<teleport to="body">
<template v-if="isShow">
<div
class="modal"
@click.self="offModal">
<div
class="modal__inner"
:style="{ width: `${parseInt(width, 10)}px` }">
<slot></slot>
</div>
</div>
</template>
</teleport>
옮기고 싶은 엘리먼트를 <teleport>
태그로 래핑한 뒤, to
속성의 값으로 selector
를 입력해서 래핑된 엘리먼트의 위치를 해당 요소로 옮길 수 있다.
React
의 Context API
처럼, 컴포넌트 구조에서 중간 단계에 있는 컴포넌트가 사용하지 않는 props
를 계속해서 전달하는 번거로움을 해결하기 위한 옵션이다.
export default {
provide() {
return {
message: this.data
}
}
}
export default {
inject: ['message']
}
아쉽게도 Provide / Inject
의 데이터는 반응성을 가지지 않기 때문에, 아래처럼 computed
함수를 이용한다.
import { computed } from 'vue';
export default {
provide() {
return {
message: computed(() => this.data)
}
}
}
또한 computed()
함수로 전달된 데이터를 정확하게 사용하려면, inject
로 받은 데이터 객체의 value
프로퍼티로 값을 가져와야 한다.
export default {
inject: ['message']
mounted() {
console.log(this.message.value);
}
}
Vue
에서 상태 관리를 좀 더 쉽고 편리하게 할 수 있도록 도와주는 라이브러리.
중앙 집중 저장소 역할을 하며, 부모 자식 관계가 아닌 컴포넌트의 데이터도 관리할 수 있다.
vuex
를 설치했다면, 아래처럼 createStore()
메서드를 이용해서 저장소를 생성할 수 있다.
import { createStore } from 'vuex';
const store = createStore({
state() {
return {
...
};
},
getters: {
...
},
mutations: {
...
},
actions: {
...
}
});
생성된 store
는 바로 사용할 수 없고, 플러그인 처럼 use()
메서드를 이용해서 등록해야 한다.
import { createApp } from 'vue';
import store from '~/store';
import App from './App.vue';
const app = createApp(App);
app.use(store);
app.mount('#app');
vuex
로 관리할 데이터를 정의하는 옵션.
this.$store.<state>
로 데이터를 가져올 수 있다.계산된 데이터를 정의하는 옵션.
getters
내부에서 정의하는 메서드는 첫 번째 매개변수로 state
가 전달되며, 이 값을 통해 state
의 데이터에 접근이 가능하다.
this.$store.getters.<method>
로 계산된 데이터를 가져올 수 있다.
값을 변경하는 메서드를 정의하는 옵션.
getters
와 마찬가지로 첫 번째 매개변수로 state
가 전달된다.
mutations
에 정의된 메서드는 this.$store.commit('<method>'[, argument])
로 호출이 가능하다.
동기적으로 동작해야 하는 메서드를 정의한다.
다른 모든 메서드를 정의하는 옵션
첫 번째 매개변수로 context
객체가 전달되며, context
객체에는 state, getters, commit, dispatch
프로퍼티가 있다.
actions
에 정의된 메서드는 this.$store.dispatch('<method>')
로 호출이 가능하다.
비동기적인 메서드를 정의할 수 있다.
별도의 파일로 분리된 모듈을 불러올 때 사용하는 옵션
기존의 store
와 구조적으로 큰 차이는 없으나, namespaced
프로퍼티를 true
로 설정해야 한다.
export default {
namespaced: true,
state() {
return {
...
};
},
getters: {
...
},
mutations: {
...
},
actions: {
...
}
};
이렇게 분리된 모듈은 아래처럼 등록할 수 있다.
import { createStore } from 'vuex';
import <module> from '<modulePath>';
export default createStore({
state() {
return {
...
};
},
getters: {
...
},
mutations: {
...
},
actions: {
...
},
modules: {
<namespace>: <module>
}
});
모듈의 state
는 this.$store.state.<namespace>.<state>
로 접근이 가능하다.
모듈의 getters
는 this.$store.getters['<namespace>/<method>']
로 호출이 가능하다.
모듈의 mutations
에 정의된 메서드는 this.$store.commit('<namespace>/<method>')
로 호출이 가능하다.
모듈의 actions
에 정의된 메서드는 this.$store.dispatch('<namespace>/<method>')
로 호출이 가능하다.
특정 모듈에 속한 옵션을 배열을 통해 전개할 수 있는 기능
vuex
패키지에 있는 mapState, mapGetters, mapMutations, mapActions
메서드를 이용해서 모듈에 있는 각종 옵션들을 좀 더 보기 쉽게 매핑할 수 있다.
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
export default {
computed: {
...mapState('<namespace>', [
'<state>',
'<state'
])
}
}
기본적으로 모든 메서드가 위의 코드처럼 ...map<option>('<namespace>', [ '<option>' ])
형태로 전개가 가능하며, namespace
를 생략하고 배열만 전달하는 경우 전역 store
에 있는 옵션을 사용하게 된다.