[Vue.js] 재사용, 유지보수를 위한 Component

geesuee·2021년 9월 29일
0

Vue.js

목록 보기
3/3
post-thumbnail

1. Component란?

웹 컴포넌트는 그 기능을 나머지 코드로부터 캡슐화하여 재사용 가능한 커스텀 엘리먼트를 생성하고 웹 앱에서 활용할 수 있도록 해주는 다양한 기술들의 모음입니다. (MDN, 웹 컴포넌트)

코드를 간소화하고 재사용 할 수 있게 하는 구성 요소
✅ 컴포넌트를 조합하여 전체 애플리케이션 작성 → 조합하여 화면을 구성할 수 있는 블록
✅ 재사용성의 향상이 주 목적


⭐ 한 애플리케이션 내 반복되는 UI를 하나로 만들어 재사용 → 개발 생산성 향상 및 유지 보수 용이
⭐ 컴포넌트 단위로 기능 테스트 가능
⭐ Vue devtools 등으로 컴포넌트 단위로 전달된 속성 확인 가능, 디버깅 용이




2. 등록 방식에 따른 Component 종류

1) 전역 컴포넌트

ㄴ 애플리케이션 전체, 여러 Vue instance에서 사용 가능

  • Vue instance를 필수적으로 만들고, component를 만들어야함
  • 전역 컴포넌트더라도 Vue instance가 만들어져있어야 컴포넌트 적용 가능함
  • Vue.component(사용자 정의 tag 이름, 화면 구성{template, methods 등}) 형식으로 작성
  • html body에서는 사용자 정의 tag로 template 표현
<script>
Vue.component("global", {
  template: "<b>전역 컴포넌트</b>",
});

new Vue({
  el: "#app1",
});
</script>

2) 지역 컴포넌트

ㄴ 컴포넌트가 생성된 특정 Vue instance 내에서만 사용 가능

  • Vue instance를 필수적으로 만들고, component를 만들어야함
  • Vue instance 내부에 component를 property로 만들어주어, 해당 Vue instance에서만 사용할 수 있는 지역 컴포넌트 생성
  • html body에서는 사용자 정의 tag로 template 표현
<script>
new Vue({
  el: "#app1",
  components: {
    "local": {
      template: "<b>로컬 컴포넌트<b>",
    },
  },
});
</script>

3) 주의사항

  • 위의 컴포넌트 등록 예시 코드에서처럼 template를 문자열로 지정해주는 경우, 꼭 상위 tag로 감싸주어야 함
    template: "글로벌 컴포넌트와 로컬 컴포넌트"
    template: "<span>글로벌 컴포넌트와 로컬 컴포넌트<span>" ⭕ span tag로 감쌈



3. Vue Component 간 통신

0) 상위, 하위 컴포넌트 관계

  • 개별 컴포넌트는 유효 범위가 독립적, 따라서 다른 컴포넌트 값을 직접적으로 참조 불가
  • 상위 → 하위 방향으로 데이터를 전달할 때는 props
  • 하위 → 상위 방향으로 데이터를 전달할 때는 $emit(emit events)

1) props : 상위 → 하위

: 상위 컴포넌트에서 하위 컴포넌트로 name 데이터 전달, message라는 변수에 받아서 콧수염 괄호 사용 출력

  • 부모 : Vue instance와 연결된 <div id="app3">
  • 자식 : Vue component의 template인 <btn-com3>
  • 부모인 Vue instance의 data 중 name 값 전달
  • 자식인 Vue component에 props property 생성, 전달된 데이터를 보유할 변수 message 선언
  • 사용자 정의 tag <btn-com3>v-bind:message="name" 으로
    부모 컴포넌트의 name 값과 자식 컴포넌트의 message 값 바인딩
  • 자식 컴포넌트 내부 template에서 콧수염 괄호 사용하여 message 출력

2) $emit : 하위 → 상위

showLog method를 통해 하위 컴포넌트에서 상위 컴포넌트로 event-data1, event-data2 전달,
상위 컴포넌트의 viewData method를 통해 전달받은 값으로 상위 컴포넌트 데이터 값 수정

  • 부모 : Vue instance와 연결된 <div id="app5">
  • 자식 : Vue component의 template인 <child-com>
  • 자식인 Vue component의 template은 button tag
  • 해당 버튼을 누르면 자식 컴포넌트의 showLog 메소드가 실행되도록 v-on:click='showLog' 로 이벤트 처리
  • showLog 메소드가 실행되면 $emit(key, data) 형식으로 데이터 전달
  • 사용자 정의 tag <child-com>v-on:event-data1="viewData"
    <child-com> tag에서 버튼 클릭 등 이벤트가 발생하면 부모 컴퍼넌트의 viewData 메소드가 실행되도록 이벤트 처리
  • viewData 메소드가 실행되면 parameter로 넘어온 event-data1을 해당 컴포넌트의 데이터 속성 중 하나인 msg에 할당
  • 콧수염 괄호 사용하여 msg 출력



4. 리뷰 코드(📋 Student Information 📋)

오늘 학습한 내용을 복습하면서 작성해 본 코드 🏫Student Information👧

  • 컴포넌트=재사용! 동일한 template으로 학생 정보 출력
  • props 활용하여 상위 컴포넌트에서 하위 컴포넌트로 학생 정보 데이터 전달
    (상위 컴포넌트의 data - 하위 컴포넌트 info 바인딩)
  • $emit 활용하여 하위 컴포넌트에서 input으로 입력받은 데이터 상위 컴포넌트로 전달하여 저장

<!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>step14.componentReview.html</title>

        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <h1>📋 Student Information 📋</h1>
        <br />
        <div id="stu1">
            <t1 v-bind:info="data" v-on:status="viewStatus"></t1>
            <ul>
                <li>
                    Send Message :
                    <input id="input1" type="text" />
                    <t2 v-on:event1="viewMsg"></t2>
                </li>
            </ul>
        </div>

        <br /><br />

        <div id="stu2">
            <t1 v-bind:info="data" v-on:status="viewStatus"></t1>
            <ul>
                <li>
                    <input id="input2" type="text" />
                    <t2 v-on:event2="viewMsg"></t2>
                </li>
            </ul>
        </div>

        <!-- TEMPLATE -->
        <template id="basicInfo">
            <div>
                <h3>📍 Student {{info.number}}</h3>
                <ul>
                    <li>Name : {{info.name}}</li>
                    <li>Age : {{info.age}}</li>
                    <li>Major : {{info.major}}</li>
                    <li>Status : {{info.status}}</li>
                    <li>
                        Set status :
                        <button v-on:click="gStatus">good</button>
                        <button v-on:click="bStatus">bad</button>
                    </li>
                    <li>Message : {{info.msg}}</li>
                </ul>
            </div>
        </template>

        <script>
            Vue.component("t1", {
                template: "#basicInfo",
                props: ["info"],
                methods: {
                    gStatus: function () {
                        this.$emit("status", "good");
                    },
                    bStatus: function () {
                        this.$emit("status", "bad");
                    },
                },
            });

            Vue.component("t2", {
                template: "<button v-on:click='sendMsg'>send</button>",
                methods: {
                    sendMsg: function () {
                        let msg1 = document.getElementById("input1").value;
                        let msg2 = document.getElementById("input2").value;
                        this.$emit("event1", msg1);
                        this.$emit("event2", msg2);
                    },
                },
            });

            new Vue({
                el: "#stu1",
                data: {
                    data: {
                        number: 1,
                        name: "김공부",
                        age: 20,
                        major: "Educational Technology👩‍🏫",
                        status: "___",
                        msg: [],
                    },
                },
                methods: {
                    viewStatus: function (v) {
                        console.log(v);
                        console.log(typeof v);
                        this.data.status = v;
                    },
                    viewMsg: function (v) {
                        console.log(v);
                        this.data.msg.push(v);
                    },
                },
            });
            new Vue({
                el: "#stu2",
                data: {
                    data: {
                        number: 2,
                        name: "김학생",
                        age: 20,
                        major: "Computer Science👨‍💻",
                        status: "___",
                        msg: [],
                    },
                },
                methods: {
                    viewStatus: function (v) {
                        console.log(v);
                        console.log(typeof v);
                        this.data.status = v;
                    },
                    viewMsg: function (v) {
                        console.log(v);
                        this.data.msg.push(v);
                    },
                },
            });
        </script>
    </body>
</html>
profile
기록하는 오늘의 노력🌻

0개의 댓글