데브코스 38일차 TIL : Vue [플러그인, mixin, teleport, provide/inject, store, mapping]

te-ing·2021년 10월 1일
0
post-thumbnail

플러그인 만들기

// fetch.js
export default {
  install(app, options) {
    app.config.globalProperties.$fetch = (url, opts) => {
      return fetch(url, opts).then(res => res.json())
    }
    // fetch(url, options).then(res => res.json()).then(res => console.log(res))
  }
}
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import fetchPlugin from '~/plugins/fetch'

const app = createApp(App)
app.use(fetchPlugin)
// app.use(fetchPlugin, { // 옵션사용시
// 	pluginName: '$myName' // pluginName: 이름지정	
// })  // app.config.globalProperties.[options.pluginName || '$fetch']
app.mount('#app')

// App.vue
export default {
  components: {
    Hello
  },
  data() {
    return {
      msg: 'Hello Vue!'
    }
  },
  created() { // created와 mounted는 비동기를 보장하지 않음
    this.init()
  },
  methods: {
    async init() {
      const res = await this.$fetch('https://jsonplaceholder.typicode.com/todos/1').then(res => console.log(res))    
      console.log(res, 'Done!')
    }
  }
}

export default로 install 이라는 이름의 함수를 통해 app과 option(이름변경가능)을 가지는 원하는 플러그인을 만들 수 있다.

install 안에는 app(변경가능).config.globalProperties."$함수" = (옵션, 옵션) ⇒ {} 으로 만들 수 있으며, 위 코드는 자바스크립트 fetch를 간략화하는 함수이다.

install의 2번째 인자로 쓰인 options은 등록할 때 쓰는 옵션으로, pluginName등을 설정할 수 있다.

믹스인

export default {
  data() {
    return {
      count: 1,
      msg: 'Hi~'
    }  }  }
  • mixin은 라이프사이클(created..), methods 사용가능
  • mixins: ['mixin', ...]로 사용할 mixin 정의하고 사용
  • 믹스인보다 컴포넌트이 우선권을 가지기 때문에 컴포넌트에서 재정의 가능
  • 라이프사이클은 컴포넌트와 함께 모두 호출됨

eslint 비활성화

<!-- eslint-disable -->부터
<!-- eslint-enable --> 까지 eslint 비활성화

components 모아서 사용

//components/fields/index.js'
export { default as TextField } from './TextField'
export { default as SimpleRadio } from './SimpleRadio'
//App.vue
~~import TextField from '~/components/fields/TextField'
import SimpleRadio from '~/components/fields/SimpleRadio'~~
import * as FieldComponents from '~/components/fields/index.js'

export default {
  components: {
    ...FieldComponents
  },

js파일에 각 컴포넌트 파일의 import와 동시에 내보내주는 export { default as ...} from './...' 을 한곳에 모아 App.vue에서에서import * as FieldComponents from '~/components/fields/index.js' , components: { ...전개연산자Component}를 사용하면 압축해서 쓸 수 있다.

Teleport

상위태그를 기준으로 레이아웃이 정해지는 등의 상황에서 원하는 태그의 위치에서 보여줄 수 있도록 해주는 기능

<teleport to="body">...</teleport>로 감싸면 body 바로 아래의 태그에서 나타나는 것처럼 보여줄 수 있음

provide / inject

바로 아래의 컴포넌트에 속성을 전달하려면 Prop으로 내려주면 되지만, 멀리있는 특정 컴포넌트는 거쳐야할 컴포넌트가 생기면서 복잡해진다. 이때 보내주려는 컴포넌트에 provide를, 받는 컴포넌트에 inject를 사용한다.

//App.vue
import Parent from '~/components/Parent'
import { computed } from 'vue'
export default {
    provide() {
      return {
				// msg: this.msg
        msg: computed(() => this.msg)
      }
    }
//Child.vue
****  <h2>Child! / {{ msg.value }} </h2> //<h2>Child! / {{ msg }} </h2>
export default {
  inject: ['msg']
}

provide()한 값은 provide한 컴포넌트의 모든 하위속성에서 inject를 이용해 사용할 수 있다.

하지만 provide()로 제공한 값은 반응성을 가지지 않기 때문에 반응형 데이터를 만들기 위해서는 import { computed } from 'vue' 를 이용해 computed 함수를 가져와서 provide하려는 컴포넌트에 msg를 반환하는 computed함수를 넣고, inject하는 html 데이터에 .value를 붙여줘야 한다.

store 모듈화

//index.js
export default createStore({
  state() {
    return {
      msg: 'Hello Vue?!'
    }  },
  getters: {},
  mutations: {},
  actions: {},
  modules: {
    message // message: message
  }  })
// message.js
export default {
  namespaced: true,
  state() {
    return {
      message: 'Hello Store Module~~'
    }  }  }

//App.vue
computed: {
	storeMsg() {
	      return this.$store.state.msg // 전역으로 사용할 때
	    },
	storeMessage() {
	  return this.$store.state.message.message // 모듈로 사용할 때
			}
	reversedMessage() {
	      return this.$store.getters['message/reversedMessage'] 
	    }
		},
  methods: {
    increaseCount() {
      this.$store.commit('count/increaseCount')
    },

index.js에서 moduels:{ 필요한 모듈 }을 넣고, 모듈 파일(message.js)에서 namespaced: true 옵션을 넣어준다. modules의 객체는 호출명: 호출값 으로 이루어져 있으므로 호출명을 원하는 값을 바꿀 수도 있다.
store의 module을 사용하는 곳에서는 this.$store.state.message.message 같이 모듈 명을 불러와서 사용하면 되고, methods의 경우 commit에서 '모듈명/호출함수' 식으로 사용한다.

state, getterscomputed, mutations, actionsmethods으로 들어간다.

getters는 특이하게 namespaced/함수명 으로 사용하는데, 중간에 /가 들어가기 때문에 this.$store.getters['message/reversedMessage'] 처럼 대괄호와 따옴표로 감싸줘야한다.

mapping

// mapping 전
export default {
  computed: {
    count() {
      return this.$store.state.count.count
    },
    message() {
      return this.$store.state.message.message
    },
    reversedMessage() {
      return this.$store.getters['message/reversedMessage']
    }
  },
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'

export default {
  computed: {
    ...mapState('count', [
      'count',
      '',
      ''
    ]),
    ...mapState('message',[
      'message'
    ]),
    ...mapGetters('message', [
      'reversedMessage'
    ])
  },

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex' 을 사용한 후 ...mapState('namespaced',[ 'state1', 'state2', ...]) 같이 사용된다.

전역객체의 경우, namespaced없이 바로 ...mapState(['msg'])처럼 사용하면 된다.

전자에 비해 권장되는 mapping방법은 한번에 가져올 state가 많을 때 유용하다.

profile
병아리 프론트엔드 개발자🐣

0개의 댓글