관리 메뉴

여름 언덕에서 배운 것

[Vue3시작하기] Event Emit 소개 본문

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

[Vue3시작하기] Event Emit 소개

잔뜩 2023. 10. 16. 01:36

Event Emit 소개

다시한번 말하지만 Emit 에서 이벤트 발생은 UI 이벤트가 아니다.

컴포넌트 통신 방법 중 하위 컴포넌트에서 상위 컴포넌트로 통신하는 방법을 말한다.

 

백틱의 장점

JavaScript의 **템플릿 리터럴(Template Literals)**입니다.

ES6 (ES2015)에서 도입된 이 기능은 문자열을 더 쉽게 다룰 수 있게 해줍니다.

템플릿 리터럴의 주요 장점은:

1. **멀티 라인 문자열**: 문자열을 여러 줄에 걸쳐서 작성할 수 있습니다. 이전에는 문자열을 여러 줄에 나눠 작성하려면 복잡한 방법을 사용해야 했지만, 템플릿 리터럴을 사용하면 그저 줄바꿈만으로 간단하게 처리할 수 있습니다.
  
   ```javascript
   const multiLine = `
   This is a line.
   And this is another line.
   `;
   ```

2. **표현식 삽입**: `${...}` 구문을 사용하여 문자열 내부에 변수나 표현식의 값을 직접 삽입할 수 있습니다.

   ```javascript
   let name = "John";
   console.log(`Hello, ${name}!`); 

 // Outputs: Hello, John!
   ```

위의 코드 예제에서, 템플릿 리터럴은 Vue 컴포넌트의 `template` 옵션을 정의하는데 사용되었습니다.

 이는 여러 줄에 걸친 HTML 구조를 깔끔하게 정의하는데 매우 유용합니다.

 

컴포넌트에서 app-contents 만들려고 했는데 내용이 너무 길어서 변수로 따로 뺌

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<div id="app">
    <app-contents></app-contents>
</div>
<script>
    var appContents = {
        template: `
        <p>
            <button v-on:click="sendEvent">갱신</button>
        </p>`
        ,
        methods: {
            sendEvent() {
                this.$emit('refresh');
            }
        },
    }
    Vue.createApp({
        components: {
            'app-contents': appContents

        }

    }).mount('#app')
</script>

Vue.createApp()은 methods 하면 안되나..?

`methods`는 Vue 인스턴스 또는 컴포넌트 내에서 정의된 함수를 포함하는 옵션입니다. 

`Vue.createApp({ ... })`에서 정의되는 것은 **루트 인스턴스**입니다. 반면, `appContents`와 같은 객체는 **컴포넌트 정의**를 나타냅니다.

컴포넌트와 루트 인스턴스는 모두 Vue 인스턴스이지만, 구조와 사용법이 조금 다릅니다. 각 컴포넌트는 독립적인 스코프를 가지며, 각 컴포넌트는 자신만의 데이터, 메소드, 계산된 속성 등을 가질 수 있습니다. 이렇게 되면 각 컴포넌트는 독립적으로 동작하고 재사용될 수 있습니다.

### 예제로 살펴보기

루트 인스턴스에서 메소드를 정의하는 예:

Vue.createApp({
    data() {
        return {
            message: "Hello from Root!"
        };
    },
    methods: {
        rootMethod() {
            console.log(this.message);
        }
    },
    components: {
        'app-contents': appContents
    }
}).mount('#app');



위에서 `rootMethod`는 루트 인스턴스에 속하므로 루트 인스턴스의 템플릿에서만 접근할 수 있습니다.

컴포넌트에서 메소드를 정의하는 예:

var appContents = {
    data() {
        return {
            message: "Hello from Component!"
        };
    },
    methods: {
        componentMethod() {
            console.log(this.message);
        }
    },
    template: `
    <button @click="componentMethod">Click me!</button>
    `
}


여기서 `componentMethod`는 `appContents` 컴포넌트에 속하므로, 해당 컴포넌트의 템플릿에서만 접근할 수 있습니다.

### 요약

- 루트 인스턴스와 각 컴포넌트는 독립된 스코프를 가집니다.
- 루트 인스턴스의 `methods`는 루트 인스턴스의 템플릿에서만 사용할 수 있습니다.
- 컴포넌트의 `methods`는 해당 컴포넌트의 템플릿에서만 사용할 수 있습니다.
- `methods`를 어디에 정의하느냐에 따라 해당 메소드가 어디에서 사용될 수 있는지가 결정됩니다.

 

스코프가 뭐야?

 "스코프(scope)"는 프로그래밍에서 중요한 개념이며,

변수나 함수가 코드의 어느 부분에서 접근 가능한지를 결정하는 범위를 의미합니다.

스코프의 개념을 이해하기 위한 간단한 예제를 들어보겠습니다.

let globalVar = "I am global!";  // 전역 스코프

function someFunction() {
    let localVar = "I am local!";  // 지역(함수) 스코프

    console.log(globalVar);  // "I am global!"
    console.log(localVar);   // "I am local!"
}

console.log(globalVar);  // "I am global!"
// console.log(localVar);   // Error! localVar is not defined


1. **전역 스코프(Global Scope)**: 코드 전체에서 접근 가능한 변수를 정의합니다.

 위의 예제에서 `globalVar`는 전역 변수로, 코드 어디에서나 접근할 수 있습니다.

2. **지역 스코프(Local Scope) 또는 함수 스코프(Function Scope)**: 

함수 내부에서만 접근 가능한 변수를 정의합니다. `someFunction` 내부의 `localVar`는 지역 변수로, 

해당 함수 밖에서는 접근할 수 없습니다.

### Vue와 스코프
Vue에서 스코프의 개념은 컴포넌트 구조에서 특히 중요합니다.

- 각 Vue 컴포넌트는 독립적인 스코프를 가집니다.
- 컴포넌트의 데이터, 메소드, 계산된 속성 등은 해당 컴포넌트 내에서만 직접 접근할 수 있습니다.
- 하위 컴포넌트로 데이터를 전달하려면 `props`를 사용하며, 하위 컴포넌트에서 상위 컴포넌트로 이벤트를 보내려면 `$emit`을 사용합니다.

요약하면, 스코프는 변수나 함수가 어디서 접근 가능한지, 어디서 "보이는지"를 결정하는 범위입니다. 

이 개념은 코드의 어느 부분에서 어떤 데이터나 기능에 접근할 수 있는지를 이해하는 데 중요합니다.

 

 

개발자도구 - timeline에서 확인 가능

<!-- app-contents.vue -->
<template>
    <p>
        <button @click="sendEvent">갱신</button>
    </p>
</template>

<script>
export default {
    setup() {
        const sendEvent = () => {
            emit('refresh');
        }

        return {
            sendEvent
        };
    }
}
</script>
728x90