Vue

버튼 컴포넌트에서 상위 컴포넌트의 함수 실행시키는 방법 - emit

milliwonkim 2022. 6. 18. 23:47
반응형
SMALL

React에서는 다음과 같이 String, Boolean 값이든, 함수든 다 props로 내려서 그대로 실행할 수 있습니다

const AComponent = () => {
    const [exampleString, setExampleString] = useState('')    
    const handleRoute = () => {
        history.push('/some-route')
    }
    
    return (
        <BComponent
          exampleString={exampleString}          
          handleRoute={handleRoute}        
        />    
    )
 }
          
const BComponent = ({ exampleString, handleRoute }) => {
    return (
        <button onClick={handleRoute}>클릭</button>
  	)
  }

하지만 Vue는 이것과 조금 다른 방법이 존재합니다. Vue에서는 상위 컴포넌트의 함수를 실행시키기 위해서는 emit이라는 것을 이용할 수 있습니다

****TypeScript with Composition API | Vue.jsThis page assumes you've already read the overview on Using Vue with TypeScript. When using , the defineProps() macro…** vuejs.org

<template>
  <header class="header" ref="refs">
    <div class="logo-title-box">
      <p class="logo-title">ALLIGHT</p>
    </div>
    <nav class="nav-list">
      <v-app-bar-nav-icon v-if="show"></v-app-bar-nav-icon>
      <a-button
        v-else
        :key="headerButton.id"
        v-for="headerButton in headerList"
@clickHandler="handleRoute(headerButton.link)"
      >
        {{ headerButton.name }}
      </a-button>
    </nav>
  </header>
</template><script>
import { ref } from '@vue/composition-api';
import router from '@/router';
import { HEADER_BUTTONS } from '@/constants/constants';
import AButton from './AButton.vue';
import useResize from '../hooks/useResize';export default {
  name: 'a-header',
  components: {
    'a-button': AButton,
  },
  setup() {
    const headerList = ref(HEADER_BUTTONS);    const refs = ref(null);
    const show = ref(false);
    const handleRoute = (link) => {
      if (window.location.pathname !== link) {
        router.push(link);
      }
    };    return {
      refs,
      show,
      headerList,
      handleRoute,
    };
  },
};
</script>

button 컴포넌트에서 handleRoute를 실행시키기 위해 clickHandler라는 것을 bind해줍니다.

그리고 하위 컴포넌트인 AButton 컴포넌트에서는 emit을 합니다.

// @/components/AButton<template>
  <button@click="handleClick" class="default">
    <div class="button-label-box">
      <slot />
    </div>
  </button>
</template><script>
const CLICK_HANDLER = 'clickHandler'export default {
  name: 'a-button',
  setup(_, context) {
    function handleClick() {
      context.emit(CLICK_HANDLER);
    }return { handleClick };
  },
};
</script>

vue에서도 react처럼 함수를 props로 내려서 바로 사용하게 할 수 있습니다. 하지만, emit의 존재 이유를 살펴보면, emit은 하위 컴포넌트에서, 상위컴포넌트의 데이터를 업데이트 해야한다는 사실만 알려주고, 진짜 업데이트는 상위컴포넌트에서 합니다.

즉 props drilling에 비해, 하위와 상위 컴포넌트는 분리하여 사용할 수 있다라는 장점이 emit에 있다고 볼 수 있습니다.

반응형
LIST