Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

dearbeany

[Vue] 이벤트 핸들링(v-on) | 바인딩(ref, v-bind, v-model) | 뷰 컴포넌트 본문

Vue.js

[Vue] 이벤트 핸들링(v-on) | 바인딩(ref, v-bind, v-model) | 뷰 컴포넌트

dearbeany 2022. 11. 2. 13:26
더보기

1. Vue Event Handling (v-on)

- event.preventDefault()

- Vue Key Modifier (keyup)

2 Vue Bindings

- ref, @refs

- Class Bindings (v-bind)

- Form Input Bindings (v-model)

3. Vue Component 

- 전역 컴포넌트 Vue.Component()

- 지역컴포넌트 components

- <template> 사용 시 주의점

1. Vue Event Handling 

- v-on 디렉티브를 사용하여 DOM 이벤트를 듣고 트리거 될 때 JS를 실행가능

<button @click="count+=1">클릭</button>

- 많은 이벤트 핸들러의 로직은 복잡하여 v-on 속성 값으로 작성X. method이름을 작성한다.

<button @click="greet">인사</button>

- 메소드명을 직접 바인딩 하는 대신 인라인 JS구문에 메소드를 사용하기도

    <div id="app">
        <button @click="greet('수빈')">인사</button>
        <button @click="greet2($event, '수빈2')">인사2</button>
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            methods : {
                greet(msg) {
                    alert(`Hello ${msg}`);
                },
                greet2(e, msg) {
                    alert(`Hello ${msg}`);
                    console.log(e);
                }
            },
        })
    </script>

인사2 클릭할 경우

 

 

event.preventDefault()

- 제출 이벤트가 페이지를 다시 로드하지 않음 (ex. submit 후 자동 새로고침 되는 걸 방지)

- 이벤트 핸들러 내부에서 event.preventDefault() 등을 호출하는 것은 보편적

- 메소드 내에서 쉽게 작업을 할 수 있지만(페이지 이동막기2), methods는 DOM의 이벤트를 처리하는 것 보다 data 처리를 위한 로직만 작업하는 것이 좋음.(페이지 이동막기3)

    <div id="app">
        <h2>페이지 이동</h2>
        <a href="test03.html" @click="sendMsg1">페이지 이동막기1</a> <!-- 안 막아짐 -->
        <a href="test03.html" @click="sendMsg2">페이지 이동막기2</a> <!-- 막아지나 메소드 내부에서 구현했음-->
        <a href="test03.html" @click.prevent="sendMsg1">페이지 이동막기3</a> <!-- 막아짐. 권장 형태. 2,3은 같은 결과-->
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            methods : {
                sendMsg1(){
                    alert('막아');
                },
                sendMsg2(e){
                     e.preventDefault();
                    alert('막아');
                }
            },
        })
    </script>

 

 

Vue Key Modifier

- Vue는 키 이벤트를 수신할 때 v-on에 대한 키 수식어를 추가할 수 있음. (keyup : 키보드를 눌렀다 뗄 때)

'전송' 버튼 클릭 대신 '엔터키' 를 치는 것만으로 전송하도록 코드를 작성해보자.
    <div id="app">
        <input type="text" v-model="name" placeholder="이름 입력"> <!-- 버튼을 클릭해야만 전송됨-->
        <button @click="send">전송</button> 
        <input type="text" v-model="name" placeholder="이름 입력2" @keyup="send"> <!--아무 키나 눌렀다 떼면 전송됨-->
        <input type="text" v-model="name" placeholder="이름 입력3" @keyup.13="send"> <!--엔터키 눌렀다 떼면 전송됨-->
        <input type="text" v-model="name" placeholder="이름 입력4" @keyup.enter="send"> <!--엔터키 눌렀다 떼면 전송됨-->
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            data(){
                return{
                    name : '',
                };
            },
            methods : {
                send(){
                    alert(`${this.name}`);
                }
            },
        })
    </script>

 

 

 

 

2. Vue Bindings

ref, @refs

 

$refs : ref 속성이 등록된 자식 컴포넌트와 DOM 엘리먼트 객체. (템플릿, computed에서 사용X)
ref : 엘리먼트 or 자식 컴포넌트에 대한 참조를 등록하는 데 사용.
    <div id="app">
        <input type="text" v-model="id" placeholder="검색할 ID 입력" ref="id"> 
        <button @click="search">아이디 중복체크</button> 
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            data(){
                return{
                    id : '',
                };
            },
            methods : {
                search(){
                    if(this.id.length === 0){
                        alert(`아이디를 입력해주세요`);
                        console.log(this.$refs); // 객체가 반환됨 
                        this.$refs.id.focus();
                        return;
                    }
                    alert(`아이디 중복 체크 성공`);
                }
            },
        })
    </script>

- 사용자가 아무 것도 입력하지 않고 클릭했을 때, 경고창을 띄우고 입력창을 자동 포커스 해준다

 

 

 

 

Class Bindings

- 데이터 바인딩은 엘리먼트의 클래스 목록과 인라인 스타일을 조작위해 일반적으로 사용됨.

- v-bind 를 사용, 문자열 or 객체 or 배열을 이용할 수 있음

    <style>
        div {
            width: 200px;
            height: 200px;
            border : 1px solid black;
        }
        .active{
            background-color: black;
            color: white;
        }
    </style>
    <div id="app">
        <div v-bind:class="myclass">하</div>
        <div :class="{active : isActive}">하</div>
        <button @click="toggle">다크모드</button> <!-- 누르면 두번째 상자의 모드가 토글된다 -->
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            data(){
                return{
                    myclass: {active : true},
                    isActive : false,
                };
            },
            methods : {
                toggle(){
                    this.isActive = !this.isActive;
                }
            },
        })
    </script>

 

 

 

 

 

Form Input Bindings

- v-model 디렉티브를 사용하여 <form><input>과 <textarea> 엘리먼트에 양방향 데이터 바인딩을 생성 가능

- 텍스트 영역의 보간( <textarea> {{ message }} <textarea> )은 양방향바인딩 X. v-model을 사용해야

 

더보기

<Form>태그를 이용해서 서버에 보낼 수 있는 태그는? 3개

①<Input>(안에 속성이 많은 것임) ②<textarea> ③<select>

  • text와  textarea : value, input 이벤트 사용
  • checkbox, radio : checked, change 이벤트 사용
  • select : value, change 이벤트 사용
  • v-model은 모든 form 엘리먼트의 초기 value와 checked 그리고 selected 속성을 무시함

 

 

Form : checkbox 

 

  <div id="app">
    <h2>당신이 떠나고 싶은 여행지를 선택하시오</h2>
    <input type="checkbox" id="seoul" v-model="checkedAreas" value="서울">
    <label for="seoul">서울</label>
    <input type="checkbox" id="hawaii" v-model="checkedAreas" value="하와이">
    <label for="seoul">하와이</label>
    <input type="checkbox" id="bangkok" v-model="checkedAreas" value="방콕">
    <label for="seoul">방콕</label>
    <input type="checkbox" id="sebu" v-model="checkedAreas" value="세부">
    <label for="seoul">세부</label>
    <input type="checkbox" id="chungju" v-model="checkedAreas" value="충주">
    <label for="seoul">충주</label>
  </div> 
  <script>
    const app = new Vue({
      el: '#app',
      data(){
        return {
          checkedAreas: []
        };
      },
    });
  </script>

chekedAreas에 선택한 value가 들어간다.

 

Form : radio

- 하나만 선택가능하다.

  <div id="app">
    <h2>성별을 고르시오</h2>
    <input type="radio" id="man" v-model="gender" value="남자">
    <label for="man">남자</label>
    <input type="radio" id="woman" v-model="gender" value="여자">
    <label for="woman">여자</label>
    <p>나의 성별은 {{ gender }}</p>
  </div> 
  <script>
    const app = new Vue({
      el: '#app',
      data(){
        return {
          gender: '',
        };
      },
    });
  </script>

여자를 선택할 경우, gender에 value에 저장된 값이 들어간다.

 

 

 

Form : select (다중)

- select box일 경우 선택된 항목의 value 속성의 값을 관리

  <div id="app">
    <h2>본인의 소속 캠퍼스를 선택하시오</h2>
    <select v-model="selectedArea">
      <option value="" disabled>선택하세요.</option>
      <option value="서울캠퍼스">서울</option>
      <option value="대전캠퍼스">대전</option>
      <option value="광주캠퍼스">광주</option>
      <option value="부울경캠퍼스">부울경</option>
      <option value="구미캠퍼스">구미</option>
    </select>
    <div v-if="selectedArea"> <!-- 비어있으면 안 뜨도록 -->
      소속 캠퍼스는 : {{ selectedArea }} 입니다. 
    </div>
  </div> 
  <script>
    const app = new Vue({
      el: '#app',
      data(){
        return {
          selectedArea: ''
        };
      },
    });
  </script>

 

- v-for을 사용하여 작성하기

  <div id="app">
    <h2> 선호하는 캠퍼스를 선택하시오</h2>
    <select v-model="selectedArea" multiple> <!-- 다중선택 하려면 ctrl 누르고 해야함... 번거롭 -->
      <option value="" disabled>선택하세요.</option>
      <option v-for="area in areas" v-bind:value="area.value">
        {{area.name}}
      </option>
    </select>
    <div v-if="selectedArea"> <!-- 비어있으면 안 뜨도록 -->
      소속 캠퍼스는 : {{ selectedArea }} 입니다. 
    </div>
  </div> 
  <script>
    const app = new Vue({
      el: '#app',
      data(){
        return {
          selectedArea: '',
          areas : [
            {name : '서울', value : '서울캠퍼스'},
            {name : '대전', value : '대전캠퍼스'},
            {name : '광주', value : '광주캠퍼스'},
            {name : '부울경', value : '부울경캠퍼스'},
            {name : '구미', value : '구미캠퍼스'},
        ]
        };
      },
    });
  </script>

 

 

 

 

 

3. Vue Component 

- 이전엔 여러 개의 HTML파일을 가지고 있었으나, 이제는 하나의 페이지에 부품(Component)을 조립하는 방식(SPA)

- 기본 HTML 엘리먼트를 확장하여 재사용 가능한 코드를 캡슐화 하는데 도움이 됨

- 뷰컴포넌트는 뷰인스턴스이기도 함.

- 전역(부품을 어디서든 사용) / 지역(해당 인스턴스 내에서만 사용)

 

(1) 전역컴포넌트

- Vue.Component(tagName, options)

    <div id="app">
        <my-global></my-global>
        <my-global></my-global>
    </div>
    <script>
        Vue.component('MyGlobal', {
            template: `<h2>전역 컴포넌트</h2>`
        })

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

 

 

 

 

(2) 지역컴포넌트 

- 모든 컴포넌트를 전역으로 등록할 필요X

- components 인스턴스 옵션으로 등록함으로써 다른 인스턴스/컴포넌트의 범위에서만 사용할 수 있는 컴포넌트 생성 가능

    <div id="app">
        <my-local></my-local>
        <my-local></my-local>
    </div>
    <!-- app1에서 등록한 건 지역컴포넌트이므로 app2에는 별도로 등록하지 않았기 때문에 뜨지 않음 -->
    <div id="app2">
        <my-local></my-local>
    </div>
    <script>
        const app = new Vue({
            el: '#app',
            components:{
                'my-local' : {
                    template : `<h2>지역 컴포넌트</h2>`
                }
            }
        })
        const app2 = new Vue({
            el: "#app2"
        })
    </script>

app2는 뜨지 않음

 

 

 

 

(3) <template> 태그를 사용하여 전역 컴포넌트 만들어보기

- DOM을 <template>으로 사용할 때, Vue는 템플릿 콘텐츠만 가져올 수 있기 때문에 HTML이 작동하는 방식에 고유한 몇 가지 제한 사항이 적용됨. ⓛdata는 함수여야 ②<template> 태그 안은 최상위 태그 1개

 

 

컴포넌트에서 객체 형태로 data를 사용하면?

            data: {
                msg : 'hello'
            }

Component내부에서 data를 쓸 때는 메소드 형식으로 반환해야함

- 컴포넌트는 우리가 쓸 때마다 새롭게 만들어져야 하는데, data가 객체를 반환할 경우 동일한 객체 주소를 참조한다.

- data는 반드시 함수여야 한다. data가 객체를 공유하는 문제는 새로운 데이터 객체를 반환하여야 한다.

 

 

 

    <div id="app">
        <my-comp></my-comp>
    </div>
    <template id="my-temp">
        <h2> {{ msg }} </h2>
    </template>
    <script>
        Vue.component('my-comp', {
            template: '#my-temp',
            data() {
                return {
                    msg : '<template>태그로 만든 컴포넌트'
                };
            }
        })
        new Vue({
            el: '#app'
        })
    </script>

 

● <template>태그로 Component 만들 때 주의할 점

- 최상위 태그가 하나 있고 그 안에서만 모두 작성해야 한다