VueJS CSS, Event, Component

·2022년 5월 12일
0

VueJS

목록 보기
2/5
post-thumbnail

Vue Instance 속성

Vue method

  • Vue Instance는 생성과 관련된 data 및 method의 정의 가능.
  • method 안에서 data를 "this.데이터명"으로 접근 가능.

test17

<div id="app">
      <div>data : {{message}}</div>
      <div>method kor : {{helloKor()}}</div>
      <div>method eng : {{helloEng()}}</div>
    </div>
    <script>
      new Vue({
        el: '#app',
        data: {
          message: 'Hello 싸피',
          name: '안효인',
        },
        methods: {
          helloEng() {
            return 'Hello ' + this.name;
          },
          helloKor() {
            return '안녕 ' + this.name;
          },
        },
      });
    </script>

test18

<script>
        let vm = new Vue({
            data: {
                count: 1
            },
            methods: {
                incCount() {
                    console.log("incCount 호출됨");
                    this.count++
                }
            }
        })
        vm.incCount();
        console.log(vm.count); // 2
    </script>

Vue filter

  • 뷰의 필터는 화면에 표시되는 텍스트의 형식을 쉽게 변환해주는 기능
  • filter를 이용하여 표현식에 새로운 결과 형식을 적용
  • 중괄호 보간법 {{}} 또는 v-bind 속성에서 사용 가능

test19

<script>
    Vue.filter('count1', (val) => {
      if (val.length == 0) {
        return;
      }
      return `${val} : ${val.length}`;
    });
    new Vue({
      el: '#app',
      data: {
        msg: '',
      },
      filters: {
        count2(val, alternative) {
          if (val.length == 0) {
            return alternative;
          }
          return `${val} : ${val.length}`;
        },
      },
    });
  </script>

test20 천 단위마다 , 찍기, 전화번호에 - 넣기.

<script>
      Vue.filter('price', (value) => {
        if (!value) return value;
        return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
      });
      Vue.filter('mobile', (value) => {
        if (!value || !(value.length === 10 || value.length === 11)) return value;
        return value.replace(/^(\d{3})(\d{3,4})(\d{4})/g, '$1-$2-$3');
      });
      new Vue({
        el: '#app',
        data: {
          msg1: '',
          msg2: '',
        },
      });
    </script>

Vue computed 속성

  • 특정 데이터의 변경사항을 실시간으로 처리
  • 캐싱을 이용하여 데이터의 변경이 없을 경우 캐싱된 데이터를 반환
  • Setter와 Getter를 직적 지정할 수 있음 test22
  • 작성은 method 형태롤 작성하지만, Vue에서 proxy 처리하여 property처럼 사용
    test21
<div id="app">
    <input type="text" v-model="message" />
    <p>원본 메시지: "{{ message }}"</p>
    <p>역순으로 표시한 메시지1: "{{ reversedMsg() }}"</p>
    <p>역순으로 표시한 메시지2: "{{ reversedMsg() }}"</p>
    <p>역순으로 표시한 메시지3: "{{ reversedMsg() }}"</p>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        message: '안녕하세요 싸피여러분',
      },
      methods: {
        reversedMsg: function () {
          console.log('거꾸로 찍기');
          return this.message.split('').reverse().join('');
        },
      },
    });
  </script>

Vue watch 속성

  • Vue Instance의 특정 property가 변경될 때, 실행할 콜백 함수 설정

test23

<div id="app">
    <div>
      <input type="text" v-model="a" />
    </div>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        a: 1,
      },
      watch: {
        a: function (val, oldVal) {
          console.log('new: %s, old: %s', val, oldVal);
        },
      },
    });
    console.log(vm.a);
    vm.a = 2; // => new: 2, old: 1
    console.log(vm.a);
  </script>
  • Computed는 종속된 data가 변경되었을 경우, 그 data를 다시 계산하여 캐싱한다.
  • Watch의 경우 data가 변경되었을 경우, 다른 data를 변경하는 작업을 한다.
    test24
<div id="app">
      <p>원본 메시지: "{{ message }}"</p>
      <p>역순으로 표시한 메시지: "{{ reversedMsg }}"</p>
      <input type="text" v-model="message" />
    </div>
    <script>
      const app = new Vue({
        el: '#app',
        data: {
          message: 'Hello',
          reversedMsg: '',
        },
        watch: {
          message: function (newVal, oldVal) {
            console.log(newVal, oldVal);
            this.reversedMsg = newVal.split('').reverse().join('');
          },
        },
      });
    </script>

Vue event

  • Dom Event를 청취하기 위해 v-on directive 사용
  • inline event handling
  • method를 이용한 event handling

Vue event 청취 : v-on

  • v-on directive를 사용하여 DOM 이벤트를 듣고 트리거 될 때, JavaScript를 실행할 수 있다.

test25

<div id="app">
      <button v-on:click="counter += 1">클릭</button>
      <p>위 버튼을 클릭한 횟수는 {{counter}} 번 입니다.</p>
    </div>
    <script>
      new Vue({
        el: '#app',
        data: {
          counter: 0,
        },
      });
    </script>

method event handler

  • 이벤트 발생 시 처리 로직을 v-on에 넣기 힘들다. 이 때문에 v-on에서는 이벤트 발생시 처리해야 하는 method의 이름을 받아 처리한다.

test26

<div id="app">
    <button v-on:click="greet">Greet</button>
  </div>
  <script>
    var vm = new Vue({
      el: '#app',
      data: {
        name: 'SSAFY',
      },
      methods: {
        greet: function (event) {
          alert('Hello ' + this.name + '!');
          console.dir(event.target);
        },
      },
    });

      // 또한 JavaScript를 이용해서 메소드를 호출할 수 있습니다.
      //vm.greet(); // => 'Hello Vue.js!'
  </script>

Inline method handler

  • 메소드 이름을 직접 바인딩하는 대신 인라인 JavaScript 구문에 메소드를 사용할 수도 있다.
  • 원본 DOM 이벤트에 액세스해야 하는 경우, 특별한 $event 변수를 사용해 메소드에 전달할 수도 있다.

test27

<div id="app">
      <form action="http://www.naver.com">
        <button v-on:click="greet1('SSAFY')">Greet</button>
        <button v-on:click="greet2($event, 'Ssafy')">Greet</button>
      </form>
    </div>
    <script>
      new Vue({
        el: '#app',
        methods: {
          greet1: function (msg) {
            alert('Hello ' + msg + '!');
            console.dir(event.target);
          },
          greet2: function (e, msg) {
            if (e) e.preventDefault();
            alert('Hello ' + msg + '!');
            console.dir(e.target);
          },
        },
      });
    </script>

이벤트 수식어 (Event Modifier)

  • test27에서의 event.preventDefault()와 같이 method 내에서 작업을 할 수도 있지만, method는 DOM의 이벤트를 처리하는 것보다 data 처리를 위한 로직만 작업하는 것이 좋다.
  • 이 문제를 해결하기 위해, Vue는 v-on 이벤트에 이벤트 수식어를 제공한다.
  • 수식어는 .으로 표시된 접미사이다.

test28

<div id="app">
      <h2>페이지 이동</h2>

      <a href="test29.html" @click="sendMsg1">페이지 이동 막기1</a><br />
      <a href="test29.html" @click="sendMsg2">페이지 이동 막기2</a><br />
      <a href="test29.html" @click.prevent="sendMsg1">페이지 이동 막기3</a><br />
    </div>
    <script>
      new Vue({
        el: '#app',
        methods: {
          sendMsg1() {
            alert('이동할까요?');
          },
          sendMsg2(e) {
            e.preventDefault();
            alert('이동막기');
          },
        },
      });
    </script>

키 수식어 (Key Modifier)

  • Vue는 키 이벤트를 수신할 때, v-on에 대한 키 수식어를 추가할 수 있다.

test29

<div id="app">
    아이디 :<br>
    <input placeholder="검색할 아이디를 입력하세요" v-model="id" @keyup="sendId" /><br>
    <input placeholder="검색할 아이디를 입력하세요" v-model="id" @keyup.enter="sendId" /><br>
    <input placeholder="검색할 아이디를 입력하세요" v-model="id" @keyup.13="sendId" /><br>
    <button @click.once="sendId">검색</button>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        id: '',
      },
      methods: {
        sendId() {
          alert(this.id);
        },
      },
    });
  </script>

ref, $refs

  • 뷰에서는 $refs 속성을 이용해 DOM에 접근할 수 있다.
  • 단, 뷰의 가장 중요한 목적 중 하나는 개발자가 DOM을 다루지 않게 하는 것이므로, 되도록 ref를 사용하는 것을 피하는 것이 좋다.

test30

 <div id="app">
    <h2>엘리먼트 참조하기</h2>
    <!-- 아이디 : <input type="text" v-model="id"> -->
    아이디 : <input type="text" v-model="id" ref="id" @keyup="idCheck" />
    <button @click="idCheck">아이디 중복 체크</button>
    <div v-bind:class="{success : isSuccess, fail : isFail}" v-bind:style="myStyle" v-html="msg"></div>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        id: '',
        msg: '',
        isSuccess: false,
        isFail: false,
        myStyle: {
          fontSize: '25px',
        },
      },
      methods: {
        idCheck() {
          if (this.id.length < 5 || this.id.length > 12) {
            this.msg = `아이디는 5자이상 12자리 이하입니다.`;
            this.$refs.id.focus();
            console.dir(this.$refs.id);
            this.isSuccess = false;
            this.isFail = false;
            return;
          } else {
            if (this.id === 'ssafy') {
              this.msg = `<b>${this.id}</b>는 사용할 수 없습니다.`;
              this.isSuccess = false;
              this.isFail = true;
            } else {
              this.msg = `<b>${this.id}</b>는 사용할 수 있습니다.`;
              this.isSuccess = true;
              this.isFail = false;
            }
          }
          console.log(this.$refs.id.value);
        },
      },
    });
  </script>

CSS class binding

Class binding

  • element의 class와 style을 변경.
  • v-bind : class는 조건에 따라 class를 적용할 수 있다.

test31

<div id="app">
    <div v-bind:class="{ active: isActive }">VueCSS적용</div>
    <button v-on:click="toggle">VueCSS</button>
  </div>
  <script type="text/javascript">
    new Vue({
      el: '#app',
      data: {
        isActive: false,
      },
      methods: {
        toggle: function () {
          this.isActive = !this.isActive;
        },
      },
    });
  </script>

test32

<div id="app">
      <ul>
        <li :class="{completed: todo.done}" :style="myStyle" v-for="todo in todos">
          {{todo.msg}}
          <button @click="complete(todo)" class="btn">완료</button>
        </li>
      </ul>
    </div>
    <script>
      new Vue({
        el: '#app',
        data: {
          todos: [
            {
              msg: '5시간 잠자기',
              done: false,
            },
            {
              msg: '알고리즘 1시간 공부하기',
              done: false,
            },
            {
              msg: 'Vue 1시간 공부하기',
              done: false,
            },
          ],
          myStyle: {
            fontSize: '20px',
          },
        },
        methods: {
          complete: function (todo) {
            todo.msg = todo.msg + '완료';
            todo.done = !todo.done;
          },
        },
      });
    </script>

Form Input Binding

  • v-model directive를 사용하여 폼 input과 textarea element에 양방향 데이터 바인딩을 생성할 수 있다.
    • text와 textarea 태그는 value속성과 input 이벤트를 사용한다.
    • 체크박스들과 라디오 버튼들은 checked 속성과 change 이벤트를 사용한다.
    • Select 태그는 value를 prop으로, change를 이벤트로 사용한다.

form - text, textarea


test33

<div id="app">
    <div>
      아이디 :
      <input v-model.trim="id" placeholder="아이디를 입력하세요" />
      <!-- v-model은 기본적으로 모든 key stroke가 발생할 때마다 값을 업데이트 시킨다.
           .lazy 수식어를 추가하여 change 이벤트 이후에 동기화 할 수 있습니다. -->
      <input v-model.lazy="id" placeholder="아이디를 입력하세요" />
    </div>
    <div>
      메세지 :
      <textarea v-model="message" placeholder="내용을 입력하세요"></textarea>
    </div>
    <p>{{ id }} 님에게 보내는 메세지 : {{ message }}</p>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        id: '',
        message: '',
      },
    });
  </script>

form - checkbox

  • 하나의 체크박스는 단일 boolean 값을 갖는다.
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{checked}} </label>

test34

<div id="app">
    <div>
      <p>
        이메일 수신
        <input type="checkbox" id="emailYN" v-model="email" />
        <label for="emailYN">{{ email }}</label>
      </p>
    </div>
    <div>
      <p>
        SMS 수신
        <input type="checkbox" id="smsYN" v-model="sms" true-value="Y" false-value="N" />
        <label for="smsYN">{{ sms }}</label>
      </p>
    </div>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        email: false,
        sms: 'Y',
      },
    });
  </script>
  • 여러 개의 체크박스는 같은 배열을 바인딩 할 수 있다.
  • 배열의 값과 checkbox의 value 속성이 같을 경우, 체크 처리됨.

test35

<div id="app">
    <div>당신이 가고 싶은 지역을 선택하시오</div>
    <input type="checkbox" id="buk" value="부울경" v-model="checkedAreas" />
    <label for="buk">부울경</label>
    <input type="checkbox" id="gwangju" value="광주" v-model="checkedAreas" />
    <label for="gwangju">광주</label>
    <input type="checkbox" id="gumi" value="구미" v-model="checkedAreas" />
    <label for="gumi">구미</label>
    <input type="checkbox" id="daejeon" value="대전" v-model="checkedAreas" />
    <label for="daejeon">대전</label>
    <input type="checkbox" id="seoul" value="서울" v-model="checkedAreas" />
    <label for="seoul">서울</label>
    <br />
    <span>체크한 이름: {{ checkedAreas }}</span>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        checkedAreas: [],
      },
    });
  </script>

form - radio

  • radio의 경우, 선택된 항목의 value 속성의 값을 관리.
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>t선택 : {{ picked }} </span>

test36

<div id="app">
    <div>수업을 듣는 지역을 선택하시오</div>
    <div>
      <input type="radio" id="buk" value="부울경" v-model="ckArea" />
      <label for="buk">부울경</label>
      <input type="radio" id="gwangju" value="광주" v-model="ckArea" />
      <label for="gwangju">광주</label>
      <input type="radio" id="gumi" value="구미" v-model="ckArea" />
      <label for="gumi">구미</label>
      <input type="radio" id="daejeon" value="대전" v-model="ckArea" />
      <label for="daejeon">대전</label>
      <input type="radio" id="seoul" value="서울" v-model="ckArea" />
      <label for="seoul">서울</label>
    </div>
    <span>선택한 지역 : {{ ckArea }}</span>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        ckArea: '광주',
      },
    });
  </script>

form - select

  • select box일 경우, 선택된 항목의 value 속성의 값을 관리.
  • v-model 표현식의 초기 값이 어떤 옵션에도 없으면, <select> element는 "선택 없음" 상태로 랜더링된다.

test37

<div id="app">
    <div>
      <p>수업을 듣는 지역을 선택하시오</p>
      <select v-model="selectedArea">
        <option disabled value="">선택하세요</option>
        <option value="buk">부울경</option>
        <option value="gwangju">광주</option>
        <option value="gumi">구미</option>
        <option value="daejeon">대전</option>
        <option value="seoul">서울</option>
      </select>
    </div>
    <span>선택한 지역 : {{ selectedArea }}</span><br />
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        selectedArea: '',
      },
    });
  </script>

test38

<div id="app">
    <div>
      <p>수업을 듣고자하는 지역을 선택하시오(다중가능)</p>
      <select v-model="selectedArea" multiple>
        <option disabled value="">선택하세요</option>
        <option value="buk">부울경</option>
        <option value="gwangju">광주</option>
        <option value="gumi">구미</option>
        <option value="daejeon">대전</option>
        <option value="seoul">서울</option>
      </select>
    </div>
    <span>선택한 지역 : {{ selectedArea }}</span>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        selectedArea: [],
      },
    });
  </script>

v-for를 이용한 동적 option 렌더링.

test39

<div id="app">
    <div>
      <select>
        <option value="1">1</option>
        <option value="2" selected>2</option>
        <option value="3">3</option>
      </select>
      <p>수업을 듣는 지역을 선택하시오</p>
      <select v-model="selectedArea">
        <option v-for="option in options" v-bind:value="option.value">{{ option.text }}</option>
      </select>
    </div>
    <span>선택한 지역 : {{ selectedArea }}</span>
  </div>
  <script>
    new Vue({
      el: '#app',
      data: {
        selectedArea: '',
        options: [
          { text: '서울', value: 'seoul' },
          { text: '광주', value: 'gwangju' },
          { text: '대전', value: 'daejeon' },
          { text: '구미', value: 'gumi' },
          { text: '부울경', value: 'buk' },
        ],
      },
      created() {
        param = 'gwangju';
        this.selectedArea = param;
      },
    });
  </script>

form - 수식어 (Modifiers)

  • .lazy : .lazy 수식어를 추가하여 change 이벤트 이후에 동기화 할 수 있습니다.
<input v-model.lazy="msg">
  • .number : 사용자 입력이 자동으로 숫자로 형 변환되기를 원하면, v-model이 관리하는 input에 number 수식어를 추가하면 된다.
<input v-model.number="age" type="number">
  • .trim : v-model이 관리하는 input을 자동으로 trim하기 원하면, trim 수정자를 추가하면 된다.
<input v-model.trim="msg">

Component

Component

  • Vue의 가장 강력한 기능 중 하나.
  • HTML Element를 확장하여 재사용 가능한 코드를 캡슐화.
  • Vue Component는 Vue Instance이기도 하기 때문에 모든 옵션 객체를 사용.
  • Life Cycle Hook 사용 가능.
  • 전역 컴포넌트와 지역 컴포넌트.

전역 컴포넌트 등록

  • 전역 컴포넌트를 등록하려면, Vue.component(tagName, options)를 사용.
  • 권장하는 컴포넌트 이름 : 케밥 표기법 (전부 소문자, -) 이름 표기법 참조, Style Guide(명명 규칙)

test01

<div id="app1">

  </div>
  <div id="app2">

  </div>
  <script>
    // 전역 컴포넌트 설정
    new Vue({
      el: '#app1',
    });
    new Vue({
      el: '#app2',
    });
  </script>

지역 컴포넌트 등록

  • 컴포넌트를 components 인스턴스 옵션으로 등록함으로써 다른 인스턴스/컴포넌트의 범위에서만 사용할 수 있는 컴포넌트를 만들 수 있다.

test02

<div id="app1">
    <my-local></my-local>
    <my-local></my-local>
  </div>
  <div id="app2">
    <my-local></my-local>
    <my-local></my-local>
  </div>
  <script>
    new Vue({
      el: '#app1',
      // 지역 컴포넌트 설정
    });
    new Vue({
      el: '#app2',
    });
  </script>

컴포넌트 템플릿

test03

<div id="app">
    <my-comp></my-comp>
  </div>
  <!-- template 설정 -->
  <script>
    Vue.component('MyComp', {
      template: '#MyComp',
      data() {
        return {
          msg: 'hello component',
        };
      },
    });

    new Vue({
      el: '#app',
    });
  </script>

컴포넌트 data 공유

test04 문제점.

<div id="app">
    <count-view></count-view>
    <count-view></count-view>
    <count-view></count-view>
  </div>
  <template id="CountView">
    <div>
      <span>{{ count }}</span>
      <button @click="count++">클릭</button>
    </div>
  </template>
  <script>
    let num = {
      count: 0,
    };
    Vue.component('countView', {
      data() {
        return num;
      },
      template: '#CountView',
    });
    new Vue({
      el: '#app',
    });
  </script>

test05 해결법.

<h2>컴포넌트 데이터 공유 문제 해결</h2>
    <div id="app">
      <count-view></count-view>
      <count-view></count-view>
      <count-view></count-view>
    </div>
    <template id="CountView">
      <div>
        <span>{{ count }}</span>
        <button @click="count++">클릭</button>
      </div>
    </template>
    <script>
      Vue.component('CountView', {
        template: '#CountView',
        data() {
          return {
            count: 0,
          };
        },
      });
      new Vue({
        el: '#app',
      });
    </script>

Component 간 통신

컴포넌트 간 통신

  • 상위(부모) - 하위(자식) 컴포넌트 간의 data 전달 방법.
  • 부모에서 자식 : props라는 특별한 속성을 전달. (Pass Props)
  • 자식에서 부모 : event로만 전달 가능. (Emit Event)

상위에서 하위 컴포넌트로 data 전달.

  • 하위 컴포넌트는 상위 컴포넌트의 값을 직접 참조 불가.
  • data와 마찬가지로 props 속성의 값을 template에서 사용 가능.

literal props

test06

<div id="app">
    <h2>props test</h2>

  </div>
  <script>
    //하위 컴포넌트

    new Vue({
      el: '#app',
    });
  </script>

렌더링 과정

  1. new Vue()로 상위 컴포넌트인 인스턴스를 하나 생성.
  2. Vue.component()를 이용하여 하위 컴포넌트인 child-component를 생성.
  3. <div id="app"> 내부에 <chile-component>가 있기 때문에 하위 컴포넌트가 된다. 처음 생성한 인스턴스 객체가 #app의 요소를 가지기 때문에 부모와 자식 관계가 성립된다.
  4. 하위 컴포넌트에 props 속성을 정의한다. ['propsdata']
  5. html에 컴포넌트 태그(child-component)를 추가한다.
  6. 하위 컴포넌트에 v-bind 속성을 사용하면 상위 컴포넌트의 data의 key에 접근이 가능하다. (message)
  7. 상위 컴포넌트의 message 속성 값인 String 값이 하위 컴포넌트의 propsdata로 전달된다.
  8. 하위 컴포넌트의 template 속성에 정의된 '<span>{{propsdata}}</span>'에게 전달된다.

동적 props

  • v-bind를 사용하여 부모의 데이터에 props를 동적으로 바인딩 할 수 있다.
  • 데이터가 상위에서 업데이트 될 때마다 하위 데이터로도 전달된다.

test07-1

<div id="app">
    <child-comp area="부울경" v-bind:msg="msg[parseInt(Math.random() * 5)]"></child-comp>
    <child-comp area="광주" v-bind:msg="msg[parseInt(Math.random() * 5)]"></child-comp>
    <child-comp area="구미" v-bind:msg="msg[parseInt(Math.random() * 5)]"></child-comp>
    <child-comp area="대전" v-bind:msg="msg[parseInt(Math.random() * 5)]"></child-comp>
    <child-comp area="서울" v-bind:msg="msg[parseInt(Math.random() * 5)]"></child-comp>
  </div>
  <template id="ChildComp">
    <div>
      <h2>SSAFY {{area}}지역 7기 {{msg}}</h2>
    </div>
  </template>
  <script>
    Vue.component('childComp', {
      props: ['area', 'msg'],
      template: '#ChildComp',
    });
    new Vue({
      el: '#app',
      data: {
        msg: ['굿^^', '최고!!', '실화냐?', '좋아요*', '짱!!'],
      },
    });
  </script>

test07-2

<div id="app">
    <child-comp v-for="(area, i) in areas" :key="i" :area="area" v-bind:msg="msg[parseInt(Math.random() * 5)]">
    </child-comp>
  </div>
  <template id="ChildComp">
    <div>
      <h2>SSAFY {{area}}지역 7기 {{msg}}</h2>
    </div>
  </template>
  <script>
    Vue.component('childComp', {
      props: {
        'area': String,
        'msg': {
          type: String, require: true
        }
      },
      template: '#ChildComp',
    });
    new Vue({
      el: '#app',
      data: {
        areas: ['부울경', '광주', '구미', '대전', '서울'],
        msg: ['굿^^', '최고!!', '실화냐?', '좋아요*', '짱!!'],
      },
    });
  </script>

객체의 속성 전달 props

  • 오브젝트의 모든 속성을 전달할 경우, v-bind:prop-name 대신 v-bind 만 작성함으로써 모든 속성을 prop으로 전달할 수 있다.

test08

<h2>컴포넌트 객체 데이터 전달</h2>
  <div id="app">

  </div>

  <script>

    new Vue({
      el: '#app',
      data() {
        return {
          user: {
            name: '홍길동',
            age: 22,
            email: 'hong@ssafy.com',
          },
        };
      },
    });
  </script>

사용자 정의 이벤트

  • 이벤트 이름
    • 컴포넌트 및 props와는 달리, 이벤트는 자동 대소문자 변환을 제공하지 않는다.
    • 대소문자를 혼용하는 대신에 emit할 정확한 이벤트 이름을 작성하는 것을 권장.
    • v-on 이벤트 리스너는 항상 자동으로 소문자 변환되기 때문에 이벤트 이름은 kebab-case를 사용하는 것이 권장됨.

test09

<h2>사용자 정의 이벤트</h2>
    <div id="app">
      <button v-on:click="doAction">메세지전송</button>
      <h2>{{message}}</h2>
    </div>
    <script>
      new Vue({
        el: '#app',
        data: {
          message: '',
        },
        methods: {
          doAction() {
            this.$emit('sendMsg', '안녕하세요 여러분');
          },
        },
        created() {
          this.$on('sendMsg', (msg) => {
            alert(msg);
            this.message = msg;
          });
        },
      });
    </script>

하위에서 상위 컴포넌트로 event 전달.

  • 하위 컴포넌트에서 상위 컴포넌트가 지정한 이벤트를 발생 ($emit)
  • 상위 컴포넌트는 하위 컴포넌트가 발생한 이벤트를 수신하여 data 처리

test10

<div id="app">
    <h4>당신이 좋아하는 파트를 선택하세요</h4>
    <h2>총 투표수 : {{ total }}</h2>
    <subject v-on:add-total-count="addTotalCount" title="코딩"></subject>
    <subject v-on:add-total-count="addTotalCount" title="알고리즘"></subject>
  </div>
  <script>
    Vue.component('Subject', {
      template: '<button v-on:click="addCount">{{title}} - {{ count }}</button>',
      //props 설정
      data: function () {
        return {
          count: 0,
        };
      },
      methods: {
        addCount: function () {
          this.count += 1;
          // 부모 v-on:이름 에 해당하는 이름의 이벤트를 호출

        },
      },
    });

    new Vue({
      el: '#app',
      data: {
        total: 0,
      },
      methods: {
        addTotalCount: function () {
          this.total += 1;
        },
      },
    });
  </script>

비 상하위간 통신

  • 비어있는 Vue Instance 객체를 Event Bus로 사용.
  • 복잡해질 경우, 상태관리 라이브러리인 Vuex 사용 권장.

test11

<div id="app">
    <my-count></my-count>
    <log></log>
  </div>
  <template id="myCount">
    <div>
      <input type="text" v-model.number="count" @keyup.enter="send" />
      <button @click="send">보내기</button>
    </div>
  </template>
  <template id="log">
    <div>
      <h2>{{count}}</h2>
      <ul>
        <li v-for="msg in list">{{msg}}</li>
      </ul>
    </div>
  </template>
  <script>
    const bus = new Vue();
    Vue.component('myCount', {
      template: '#myCount',
      data() {
        return {
          count: 0,
        };
      },
      methods: {
        send() {
          bus.$emit('updateLog', this.count);
          this.count = '';
        },
      },
    });

    Vue.component('Log', {
      template: '#log',
      data() {
        return {
          count: 0,
          list: [],
        };
      },
      methods: {
        updateLog(data) {
          this.count += data;
          this.list.push(`${data}을 받았습니다.`);
        },
      },
      created: function () {
        bus.$on('updateLog', this.updateLog);
      },
    });

    new Vue({
      el: '#app',
    });
  </script>
profile
SSAFY 7기

0개의 댓글