실전 오류 해결 팁/Vue

[Vue] 이벤트 발생(emit)

이우열 2023. 4. 3. 16:20
728x90

✅ 프로젝트의 구성

프로젝트 구성

 

큰 틀로 App.vue 안에 router-view를 사용하여

CountryView.vue를 보여주거나 PlaceView.vue를 보여주는 구조로 되어있습니다.

 

데이터 업데이트 과정

"country", "place" 변수가

CountryView.vue에서도 쓰이고 PlaceView.vue에서도 쓰이기 때문에

부모 컴포넌트에서 선언하여 자식 컴포넌트로 넘겨줘야겠다고 생각했습니다.

 

v-bind를 사용하여 데이터를 주고받는 것은 가능했지만

부모 컴포넌트의 데이터를 변화시킬 수는 없었습니다.

 

자식 컴포넌트에서 변화된 데이터를 부모 컴포넌트에서 변화를 주기 위해서는 이벤트를 발생시켜

부모 컴포넌트에 정의된 메소드를 호출해 부모 컴포넌트의 데이터를 변화시켜야 합니다.

 

 

✅ 부모 컴포넌트

<!-- App.vue (부모 컴포넌트) -->
<template>
  <div id="app">
    <router-view
      v-on:selectCountry="selectCountry"
      v-on:selectPlace="selectPlace"
      v-bind:propsCountry="country"
      v-bind:propsPlace="place"
    >
    </router-view>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      country: "",
      place: "",
    };
  },
  methods: {
    selectCountry(country) {
      this.country = country;
      localStorage.setItem("country", this.country);
      localStorage.removeItem("place");
      // console.log("현재 저장된 나라 " + this.country);
    },
    selectPlace(place) {
      this.place = place;
      localStorage.setItem("place", this.place);
      // console.log("현재 저장된 장소 " + this.place);
    },
  },
};
</script>

부모 컴포넌트의 구조를 보면

  • <router-view> 태그를 통해 route에 따라 보이는 컴포넌트가 다르게 구성되어 있습니다.
  • v-on을 사용하여 자식 컴포넌트에서 호출된 이벤트를 수신하는 역할을 합니다.
  • v-bind를 통해 자식 컴포넌트에 부모 컴포넌트에서 선언된 데이터를 전달합니다.
  • v-on을 통해 수신한 이벤트를 받아 선언된 메소드를 실행합니다.

 

✅ 자식 컴포넌트

<!-- CountryView.vue (자식 컴포넌트) -->
<template>
  <div>
    <HeadComponent></HeadComponent>
    <NavComponent></NavComponent>
    <div class="main">
      <div
        class="country__div"
        v-for="country in countries"
        v-bind:key="country"
        v-on:click="selectCountry($event)"
      >
        <p>{{ country }}</p>
      </div>
    </div>
  </div>
</template>

<script>
import HeadComponent from "@/components/HeadComponent.vue";
import NavComponent from "@/components/NavComponent.vue";

export default {
  name: "CountryView",
  props: ["propsCountry", "propsPlace"],
  data: () => ({
    countries: ["미국", "일본", "중국", "영국", "태국"],
  }),
  components: {
    HeadComponent,
    NavComponent,
  },
  methods: {
    selectCountry(event) {
      const text = event.target.innerText;
      console.log(text);
      this.$emit("selectCountry", text);
      this.$router.push("place");
    },
  },
};
</script>

자식 컴포넌트의 구조를 보면

  • props를 통해 부모 컴포넌트에서 전달받은 데이터를 수신합니다.
  • <div> 태그를 클릭했을 경우 selectCountry 메소드가 실행됩니다.
  • selectCountry 메소드가 실행됐을 때, this.$emit를 사용하여 상위 컴포넌트의 메소드인 selectCountry를 호출하고 text를 함께 전달합니다.

 

✏️ 정리

// 하위 컴포넌트의 내용
this.$emit('이벤트 명');

 

<!-- 상위 컴포넌트의 템플릿 -->
<div id="app">
  <child-component v-on:이벤트 명="상위 컴포넌트의 실행할 메서드 명 또는 연산"></child-component>
</div>

 

정리하자면 위의 코드 구조를 갖게 된다.

 

즉, 하위 컴포넌트에서 this.$emit을 통해 상위 컴포넌트의 이벤트를 발생시키고

상위 컴포넌트에서 하위 컴포넌트에서 받은 이벤트 명에 해당하는 상위 컴포넌트의 메서드를 실행시킨다.

 

 

 

그림으로 표현하자면 이러한 구조이다.

728x90

'실전 오류 해결 팁 > Vue' 카테고리의 다른 글

[Vue] 새로고침 시 데이터 유지  (0) 2023.04.03
[Vue] no-multiple-template-root  (0) 2023.03.22
[Vue] 라우터(Router)  (0) 2023.03.21
[Vue] 컴포넌트 생성 시 이름 규칙  (0) 2023.02.19
[Vue] 프로젝트 생성  (0) 2023.02.18