[TIL] Vue(6)

JaeungE·2022년 5월 12일
0

TIL

목록 보기
24/29
post-thumbnail

플러그인(Plugin)


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');





믹스인(Mixin)


믹스인은 여러 컴포넌트에서 반복적으로 사용하는 로직을 묶어서 재사용할 수 있도록 만드는 기능이다.

만약 믹스인의 내용이 객체 옵션인 경우, 병합을 진행하며 중복되는 값은 컴포넌트의 내용을 우선 적용하게 된다.

하지만 라이프사이클 훅은 믹스인의 훅과 컴포넌트의 훅이 모두 호출된다는 점에 유의하도록 하자.

믹스인은 기본적으로 아래처럼 객체 리터럴로 작성한다.


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>





텔레포트(Teleport)


컴포넌트 내부 데이터에는 접근이 가능한 상태로, 다른 엘리먼트에 출력할 수 있도록 만들어주는 기능.

아래는 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를 입력해서 래핑된 엘리먼트의 위치를 해당 요소로 옮길 수 있다.





Provide / Inject


ReactContext 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);
  }
}





Vuex


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');



state

vuex로 관리할 데이터를 정의하는 옵션.

  • this.$store.<state>로 데이터를 가져올 수 있다.



getters

계산된 데이터를 정의하는 옵션.

  • getters 내부에서 정의하는 메서드는 첫 번째 매개변수로 state가 전달되며, 이 값을 통해 state의 데이터에 접근이 가능하다.

  • this.$store.getters.<method>로 계산된 데이터를 가져올 수 있다.



mutations

값을 변경하는 메서드를 정의하는 옵션.

  • getters와 마찬가지로 첫 번째 매개변수로 state가 전달된다.

  • mutations에 정의된 메서드는 this.$store.commit('<method>'[, argument])로 호출이 가능하다.

  • 동기적으로 동작해야 하는 메서드를 정의한다.



actions

다른 모든 메서드를 정의하는 옵션

  • 첫 번째 매개변수로 context 객체가 전달되며, context 객체에는 state, getters, commit, dispatch 프로퍼티가 있다.

  • actions에 정의된 메서드는 this.$store.dispatch('<method>')로 호출이 가능하다.

  • 비동기적인 메서드를 정의할 수 있다.



modules

별도의 파일로 분리된 모듈을 불러올 때 사용하는 옵션

기존의 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>
  }
});

  • 모듈의 statethis.$store.state.<namespace>.<state>로 접근이 가능하다.

  • 모듈의 gettersthis.$store.getters['<namespace>/<method>']로 호출이 가능하다.

  • 모듈의 mutations에 정의된 메서드는 this.$store.commit('<namespace>/<method>')로 호출이 가능하다.

  • 모듈의 actions에 정의된 메서드는 this.$store.dispatch('<namespace>/<method>')로 호출이 가능하다.



mapping

특정 모듈에 속한 옵션을 배열을 통해 전개할 수 있는 기능

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에 있는 옵션을 사용하게 된다.

0개의 댓글