관리 메뉴

여름 언덕에서 배운 것

[Vue3시작하기] 같은 레벨의 컴포넌트간 데이터 전달 방법 본문

가랑비에 옷 젖는 줄 모른다 💻/Vue.js

[Vue3시작하기] 같은 레벨의 컴포넌트간 데이터 전달 방법

잔뜩 2023. 10. 16. 02:28

<div id="app">
    <app-header></app-header>
    <app-contents v-on:login="receive"></app-contents>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
    var appHeader = {
        data() {
            return {
                appTitle: '로그인 하세요'
            }
        },
        template: `<h1>{{appTitle}}</h1>`
    }

    var appContents = {
        template: `
        <p>
            <button v-on:click="sendEvent">로그인</button>
        </p>`
        ,
        methods: {
            sendEvent() {
                this.$emit('login');
            }
        },
    }
    Vue.createApp({
        methods: {
            receive() {
                console.log('받았다');
            }
        },
        components: {
            'app-header': appHeader,
            'app-contents': appContents
        }
    }).mount('#app')
</script>

상위 컴포넌트를 이용해야지 같은 레벨의 컴포넌트가 소통이 이뤄짐을 볼 수있다.

<div id="app">
    <app-header v-bind:appTitle="message"></app-header>
    <app-contents v-on:login="receive"></app-contents>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
    var appHeader = {
        props: ['appTitle'],
        template: `<h1>{{appTitle}}</h1>`,
    }

    var appContents = {
        template: `
        <p>
            <button v-on:click="sendEvent">로그인</button>
        </p>`
        ,
        methods: {
            sendEvent() {
                this.$emit('login');
            }
        },
    }
    Vue.createApp({
        data() {
            return {
                message: ''
            }
        },
        methods: {
            receive() {
                this.message = '로그인 완료'
                console.log('받았다');
            }
        },
        components: {
            'app-header': appHeader,
            'app-contents': appContents
        }
    }).mount('#app')
</script>

로그인 버튼 클릭 후!

 

지금 apptitle 로 소문자로 바뀐걸 볼 수 있는데  - 하이픈으로 해주면 된다.

싱글파일컴포넌트 배우고 나면 신경 안써도 되긴 합니다.

 

 

<div id="app">
    <app-header v-bind:app-title="message"></app-header>
    <app-contents v-on:login="receive"></app-contents>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
    var appHeader = {
        props: ['appTitle'],
        template: `<h1>{{appTitle}}</h1>`,
    }

    var appContents = {
        template: `
        <p>
            <button v-on:click="sendEvent">로그인</button>
        </p>`
        ,
        methods: {
            sendEvent() {
                this.$emit('login');
            }
        },
    }
    Vue.createApp({
        data() {
            return {
                message: '로그인 해주세요'
            }
        },
        methods: {
            receive() {
                this.message = '로그인 완료'
                console.log('받았다');
            }
        },
        components: {
            'app-header': appHeader,
            'app-contents': appContents
        }
    }).mount('#app')
</script>

코드 해석:

  1. <app-header v-bind:app-title="message"></app-header>:
    • app-header라는 컴포넌트를 사용하며, app-title이라는 props를 이용해 message 데이터를 전달합니다.
  2. <app-contents v-on:login="receive"></app-contents>:
    • app-contents라는 컴포넌트를 사용합니다.
    • login이라는 이벤트가 발생하면 receive라는 메서드를 호출합니다.
  3. appHeader 컴포넌트:
    • appTitle이라는 props를 받아서 화면에 제목으로 출력합니다.
  4. appContents 컴포넌트:
    • "로그인" 버튼이 있습니다.
    • 버튼을 클릭하면 sendEvent 메서드가 실행되며, 이 메서드에서는 login 이벤트를 발생시킵니다.
  5. 루트 Vue 인스턴스:
    • 초기 message는 빈 문자열입니다.
    • receive 메서드는 login 이벤트가 발생하면 실행되며, message를 '로그인 완료'로 변경하고 콘솔에 '받았다'를 출력합니다.

알겠습니다. `props`는 Vue에서 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 사용하는 메커니즘입니다. 

단계별로 `props`의 연결 과정을 살펴보겠습니다:

1. **상위 컴포넌트 (`Vue.createApp` 안의 인스턴스)**
   
   - 데이터로 `message`라는 속성을 가지고 있습니다. (`data` 속성 참조)
   - HTML에서 `<app-header v-bind:app-title="message"></app-header>` 이 부분을 보면, `v-bind:app-title="message"` 라는 코드가 있습니다. 이 코드는 상위 컴포넌트의 `message` 데이터를 `appTitle`이라는 props로 `app-header` 컴포넌트에게 전달하겠다는 의미입니다.

2. **하위 컴포넌트 (`appHeader`)**

   - `props: ['appTitle']`를 통해 `appTitle`이라는 props를 받을 준비를 합니다.
   - `template: <h1>{{appTitle}}</h1>`에서 `appTitle`을 사용하여 화면에 출력합니다.

이렇게 데이터의 흐름은 상위 컴포넌트에서 하위 컴포넌트로만 이동합니다. 

#### 시각적으로 표현하면:

- `Vue.createApp`의 `message` 데이터 -> `<app-header>` 컴포넌트의 `appTitle` props로 전달 -> `appHeader`에서 `appTitle` 사용

이 연결 고리를 통해 상위 컴포넌트의 `message` 데이터가 `appHeader` 컴포넌트의 `<h1>` 태그 안에 출력됩니다. 

즉, 상위 컴포넌트에서의 `message` 값 변경은 `appHeader` 컴포넌트의 출력 내용도 변경시킬 수 있습니다.

728x90