profile image

L o a d i n g . . .

article thumbnail image
Published 2022. 7. 27. 21:14

전역 컴포넌트 등록

Vue.component('컴포넌트 이름', {
	//컴포넌트 내용
});
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <button>컴포넌트 등록</button>
        <my-component></my-component>
    </div>

    <script>
        Vue.component('my-component', {
            template: '<div>전역 컴포넌트가 등록되었습니다!</div>'
        });

        new Vue({
            el: '#app'
        })
    </script>
</body>
</html>

 

 

 

 

 

지역 컴포넌트 등록

new Vue({
	components: {
    	'컴포넌트 이름' : 컴포넌트
    }
});

 

<body>
    <div id="app">
        <button>컴포넌트 등록</button>
        <my-component></my-component>
    </div>
    <div id="app1">
        <button>컴포넌트 등록</button>
        <my-local-component></my-local-component>
    </div>

    <script>
        Vue.component('my-component', {
            template: '<div>전역 컴포넌트가 등록되었습니다!</div>'
        });

        new Vue({
            el: '#app',
        })
        
        var cmp = {
            //컴포넌트 내용
            template: '<div>지역 컴포넌트가 등록되었습니다!</div>'
        };

        new Vue({
            el: '#app1',
            components: {
                'my-local-component': cmp
            }
        })
    </script>

순서도 중요함! Vue 생성자 만들때 cmp보다 위에가있으면 출력결과가 나오지않는다.

 

 


뷰 컴포넌트 통신과 유효범위

앵귤러, 백본과 다르게 뷰는 컴포넌트로 화면을 구성하므로 데이터 공유가 불가

- 컴포넌트 마다 자체적으로 고유한 스코프를 갖고있기때문에 다른 컴포넌트의 값을 직접참조 할 수 없다

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <button>컴포넌트 등록</button>
        <my-component></my-component>
    </div>
    <hr>
    <div id="app1">
        <button>컴포넌트 등록</button>
        <my-local-component></my-local-component>
    </div>
    <hr>
    <div id="app2">
        <button>컴포넌트 등록</button>
        <my-component1></my-component1>
        <my-component2></my-component2>
    </div>

    <script>
        Vue.component('my-component', {
            template: '<div>전역 컴포넌트가 등록되었습니다!</div>'
        });

        new Vue({
            el: '#app',
        })
        
        var cmp = {
            //컴포넌트 내용
            template: '<div>지역 컴포넌트가 등록되었습니다!</div>'
        };

        new Vue({
            el: '#app1',
            components: {
                'my-local-component': cmp
            }
        })

        var cmp1 = {
            template: '<div>첫 번째 지역 컴포넌트: {{cmp1Data}}</div>',
            data: function(){
                return {
                    cmp1Data : 100
                }
            }
        }

        var cmp2 = {
            template: '<div>두 번째 지역 컴포넌트: {{cmp2Data}}</div>',
            data: function(){
                return {
                    cmp2Data : cmp1.data.cmp1Data
                }
            }
        }

        new Vue({
            el: '#app2',
            components: {
                'my-component1': cmp1,
                'my-component2': cmp2
            }
        })
    </script>
</body>
</html>

2개의 지역 컴포넌트를 등록하고 한 컴포넌트에서 첫번째 지역 컴포넌트 값을 직접 참조했을 때

컴포넌트 유효범위(스코프)로인해 아무것도 표시되지 않는다.

 

 

 

 


상하위컴포넌트관계

 

컴포넌트간 스코프로인해 뷰 프레임워크에서는 상위-하위 컴포넌트간의 데이터 전달을 이용해야한다.

상위-하위 컴포넌트?

트리구조에서 부모노드, 자식노드처럼 컴포넌트 관계가 부모-자식 으로 이루어진 컴포넌트

 

상위에서 하위로는 props라는 속성을 전달한다.

하위에서 상위로는 기본적으로 이벤트만 전달 가능

 


상위에서 하위 컴포넌트로 데이터 전달하기

props?

Vue.component('child-component', {
props: ['props 속성이름']
});

하위 컴포넌트의 속성에 정의 한 후 

<child-component v-bind:props 속성 이름="상위 컴포넌트의 data속성"></child-component>

상위 컴포넌트의 HTML 코드에 등록된 child-component 태그에 v-bind 속성을 추가한다

v-bind 속성의 왼쪽값으로 하위 컴포넌트에서 정의한 props 속성을 넣고, 오른쪽 값으로 하위컴포넌트에 전달할 상위 컴포넌트의 data속성지정

 

 

 

예제

<body>
    <div id="app">
        <child-component v-bind:propsdata="message"></child-component>
    </div>

    <script>
        Vue.component('child-component', {
            props: ['propsdata'],
            template: '<p>{{propsdata}}</p>'
        })

        new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue! passed from Parent Component'
            }
        })
    </script>
</body>

 

예제에서 child-component를 전역으로 등록한 것 외에 상위 컴포넌트를 지정하지 않았어도 상위컴포넌트가 존재하는 것처럼 props를 받았다. 이유는 컴포넌트를 등록함과 동시에 뷰 인스턴스 자체가 상위 컴포넌트가 됐기 때문.

==> 자바 super생각하면 될듯

 

 

 


props는 상위에서 하위 컴포넌트로 전달하는것이었다면

 

이번엔 하위에서 상위 컴포넌트로 이벤트 전달하기

- 이벤트를 발생시켜(event emit) 상위 컴포넌트에 신호를 보낸다.

- 하위 컴포넌트에서 특정 이벤트가 발생하면 상위 컴포넌트에서 해당 이벤트를 수신하여 상위 메서드를 호출

 

 

이벤트 발신과 수신형식

//이벤트 발생 $emit()
this.$emit('이벤트명');

//이벤트 수신 v-on
<child-component v-on:이벤트명="상위컴포넌트의 메서드명"></child-component>

 

 

 

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

</head>
<body>
    <div id="app">
        <child-component v-on:show-log="printText"></child-component>
    </div>

    <script>
        Vue.component('child-component', {
            template: '<button v-on:click="showLog">show</button>',
            methods: {
                showLog: function(){
                    this.$emit('show-log');
                }
            }
        })

        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue! passed from Parent Component'
            },
            methods: {
                printText: function(){
                    console.log("received an event")
                }
            }
        })
    </script>
</body>
</html>​

 

child-component [show]버튼을 클릭하여 이벤트를 발생시키고 발생한 이벤트로 상위컴포넌트 printText() 메서드를 실행

 

 

 


같은레벨컴포넌트간 전달?

공통 상위 컴포넌트로 이벤트 전달 후 props

 

 

==>  상위 컴포넌트가 필요 없음에도 불구하고 같은 레벨간 통신을 위해 강제로 상위컴포넌트를 두어야하는 불편함

이를 해결하기위해 이벤트 버스 사용

 

 

이벤트버스?

개발자가 지정한 2개의 컴포넌트간 데이터를 주고받을 수 있는 방법

//이벤트 버스를 위한 추가 인스턴스 1개 생성
var eventBus = new Vue();

//이벤트를 보내는 컴포넌트 $emit
methods: {
    메서드명: function(){
    	eventBus.$emit('이벤트명', 데이터);
    }
}

//이벤트를 받는 컴포넌트 $on
methods: {
    created: function(){
    	eventBus.$on('이벤트명', function(데이터){
        ...
        });
    }
}

 애플리케이션 로직을 담는 인스턴스와는 별개로 새 인스턴스를 1개 더 생성 후 새 인스턴스를 이용하여 이벤트 송수신

 

 

<body>
    <div id="app">
        <child-component></child-component>
    </div>    
    <script>
        var eventBus = new Vue();

        Vue.component('child-component', {
            template: '<div>하위 컴포넌트 영역입니다. <button v-on:click="showLog">show</button></div>',
            methods: {
                showLog: function(){
                    eventBus.$emit('triggerEventBus', 100);
                }
            }

        })

        new Vue({
            el: '#app',
            created: function(){
                eventBus.$on('triggerEventBus', function(value){
                    console.log("이벤트를 전달받음. 전달받은 값 : ", value);
                });
            }
        })
    </script>
</body>

 

 

반응형
복사했습니다!