Frontend/Vue

Vue mitt 컴포넌트간 데이터 전송

BEOTIZA♥ 2024. 1. 1. 22:14

mitt은 모든 컴포넌트 간 데이터 통신을 지원한다.

현재 작업의 경우 SizePrice.vue -> OrderPrice.vue 컴포넌트간의 데이터 전송이 필요했다.

SizePrice.vue에서 데이터에서 받아오는 각 사이즈(S, M, L) 가격을 클릭하면 OrderPrice.vue에 보내주고,

OrderPrice.vue 구매수량에 맞춰 총가격을 구하는 작업이다.

(Vue2에서는 Event Bus을 이용해 멀리 있는 컴포넌트간 데이터를 전송했지만 Vue3에서는 사용이 불가해서 mitt 외부 라이브러리를 사용한다.)

1. mitt설치하고 main.js파일에 가서 mitt 설정한다.

  • mitt 설치
npm install mitt
  • 설치 후에 main.js파일에 가서 mitt 설정
import { createApp } from 'vue'
import App from './App.vue'
import mitt from 'mitt'

let app = createApp(App);

//mitt 라이브러리 세팅
let emitter = mitt();
//글로벌한 변수보관함
app.config.globalProperties.emitter = emitter;

app.mount('#app')

config.globalProperties는 글로벌한 변수보관함이다.  emitter를 this.emitter로 가져다 쓸 수 있다. 

 

2. 기본 mitt 데이터 송/수신 문법

  • 데이터 보내고 싶은 곳에 'this.emitter.emit'로 데이터 전송이 가능하다.
methods: {
	this.emitter.emit('작명', '데이터')
}
  •  데이터 수신하고 싶은 곳에 'this.emitter.on'을 작성한다.
mounted(){
	this.emitter.on('작명', (a)) => {
    	//데이터 수신 시 실행할 코드
        console.log(a) //a는 코드
    })
}

 

3. mitt로 클릭한 가격 다른 컴포넌트에 보내기 : SizePrice.vue -> OrderPrice.vue

//SizePrice.Vue

<script>
export default {
  data() {
    return {
      selectedPrice: 0,
      size: 0
    };
  },
  methods: {
    updatePrice(size) {
      console.log("클릭 가격" + size);
      this.selectedPrice = size;
      this.emitter.emit("selectedPrice", this.selectedPrice);
    },
  },
  computed: {
    SizePrice() {
      // 선택된 size에 따라 가격을 반환
      return this.selectedPrice;
    },
  },
};
</script>
//OrderPrice.vue

<script>
export default {
  data() {
    return {
      selectedPrice: 0, // 사용자가 선택한 사이즈에 따라 업데이트되는 가격
    };
  },
  methods: {
    updateSizePrice(sizePrice) {
      this.selectedPrice = sizePrice;
    },
  },
  mounted() {
    this.emitter.on("selectedPrice", (a) => {
      console.log("받아오는 가격은" + a);
      this.updateSizePrice(a); //메소드 호출
    });
  },
};
</script>

 

4. 선택된 금액에 구매수량별 총합계 구하기

  • 먼저 구매수량에 맞춰 가격 변화필요한 기능을 개발했다.
//html

<template>
  <div
    class="d-flex justify-content-between align-items-center card-text pt-3 border-top pad"
  >
  	<!-- 구매수량 -->
    <div class="row">
      <div class="col-auto">
        <label class="col-form-label">구매수량</label>
        <p style="text-align: left; font-size: 13px">최대 구매수량 10개</p>
      </div>
      <div class="col-auto">
        <div class="input-group">
          <span
            class="input-group-text"
            style="cursor: pointer"
            @click="minus()"
            >-</span
          >
          <input
            type="text"
            class="form-control"
            style="width: 40px"
            v-model="count"
          />
          <span class="input-group-text" style="cursor: pointer" @click="plus()"
            >+</span
          >
        </div>
      </div>
    </div>
    <div class="row pt-3 pb-3">
      <div style="text-align: right">
        <p>총합계: {{ total }}</p>
      </div>
    </div>
  </div>
</template>
  • 구매수량이 증가(plus)하고, 감소(mius)하는 함수 methods에 추가하기
<script>
export default {
  data() {
    return {
      count: 1, //카운드
      totalPrice: 0, //최종금액
      selectedPrice: 0, // 사용자가 선택한 사이즈에 따라 업데이트되는 가격
    };
  },
  computed: {
    //가격 노출 바로하려면 computed
    total() {
      return this.selectedPrice * this.count;
    },
  },
  methods: {
    plus() {
      if (this.count < 10) {
        this.count = this.count + 1;
        console.log("this.count는" + this.count);
        this.totalPrice = this.selectedPrice * this.count;
        console.log("this.totalPrice는" + this.totalPrice);
      } else {
        alert("최대 구매 수량은 10개 입니다.");
      }
    },
    minus() {
      if (this.count <= 1) {
        return;
      } else {
        this.count = this.count - 1;
        console.log("this.count는" + this.count);
        this.totalPrice = this.selectedPrice * this.count;
        console.log("this.totalPrice는" + this.totalPrice);
      }
    },
    updateSizePrice(sizePrice) {
      this.selectedPrice = sizePrice;
    },
  },
  mounted() {
    this.emitter.on("selectedPrice", (a) => {
      console.log("받아오는 가격은" + a);
      this.updateSizePrice(a); //메소드 호출
    });
  },
};
</script>

5. 오류 발견

SizePrice.vue selectePrice 데이터를 OrderPrice.vue 에 전송 되는 걸 확인했고,
구매수량도 selectePrice 에 맞춰 업데이트 되는데, 

구매수량을 수정한 상태에서 다른 사이즈를 선택하면 구매수량이 초기화되지 않는 이슈가 생김

(내가 S사이즈 3잔 주문하다가 M사이즈 1잔 추가하고 싶을 때 수량이 자동으로 1로 초기화 되야 되는데,

M사이즈 수량이 3부터 세팅되어 있어서 -로 수량을 줄여야함)

📌 이 오류는  watch를 사용해서 함수를 실행해서 해결했는데, 그 과정은 아래에 정리했다. ▼ ▼ ▼

 

[Vue] watch 사용해서 오류 해결하기

Watch는 객체 또는 배열과 같은 복잡한 데이터 구조에서도 사용할 수 있다. Watch를 사용하면 이터의 변경을 감시하고 , 해당 데이터가 변경될 때 특정 동작을 수행할수 있다. 구매수량을 수정한 상

rangyi.tistory.com


이렇게 하는게 맞나 -0- 

작업 했던 부분을 다시 되짚어가면 기록하려니 시간이 꽤 걸렸다

그래도 다시한번 리뷰 하면서 머릿속에서 정리한 의미있는 시간이었다.

오늘은 새해라 오전엔 가족행사가 있어서 블로그 기록하지 못할까 불안했는데 그래도 마음속에 잊지않고 계획하고 있으니 

결국 저녁에 잠깐 스타벅스가서 들러서 기록을 마쳤다ㅎㅎ 

또 다시 내일 부터 시작. 앞만 보고 달려가기를 

24년엔 더 적극적으로 공부하자!! 

 

 

'Frontend > Vue' 카테고리의 다른 글

Vue 반복문 v-for  (2) 2024.01.03
Vue 서버로 ajax 요청하기  (0) 2024.01.02
Vue Vscode snippet 만들기  (0) 2023.12.31
Vue 장바구니 구매수량 총합계  (0) 2023.12.28
Vue 데이터바인딩(Data-Binding) 초간단 정리  (0) 2023.12.22