Vue.js 간단정리 #10 Vue Form and Two-way Binding

Jake Seo·2020년 5월 15일
0

Vue.js-간단정리

목록 보기
10/10

Vue.js 간단정리 #10 Vue Form and Two-way Binding

Intro

https://www.vuemastery.com/courses/intro-to-vue-js 에 정리된 공식 Vue 무료 강의에 있는 내용을 짧게 정리해보려 한다.

폼과 양방향 바인딩 다루기

폼은 사람이 사이트에서 회원가입할 때 입력하는 양식 같은 것이다.

개인적인 생각으로 웹개발을 처음 시작할 때 처리하기 까다로워지기 시작하는 부분이 폼인 것 같다. 폼을 사용할 때부터 스크립트의 데이터와 화면의 데이터를 일치시키는 일이 많고, 서버와 통신할 일도 많아진다.

이전에 다뤘던 바인딩 생각해보기

이전에도 v-bind:를 이용해서 데이터 바인딩을 해봤는데, 그건 일방향 바인딩이었다. 스크립트 내부에 있는 데이터를 화면으로 빼내주긴 하지만 화면에 있는 데이터를 다시 스크립트로 가져가주지는 않는다.

양방향 바인딩

양방향 바인딩이란, 우리가 input에서 무언가 입력하면 그게 스크립트에 적용이 되기도 하고 또 스크립트의 데이터가 바뀌면 그게 다시 input에도 적용이 되고 이렇게 양쪽으로 바인드가 된 상태를 말하는 것이다.

폼 예제 만들어보기

예제로는 방명록 시스템을 만들어 볼 것이다.

먼저 아래와 같이 기본 틀을 만들었다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>TEST!!</title>
  </head>
  <body>
    <div id="app">
      <guest-book></guest-book>
      <div>등록된 방명록이 존재하지 않습니다.</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      // 앞에 선언해야 함
      Vue.component('guest-book', {
        template: `
        <div>
          <input v-model="nickname" placeholder="닉네임을 입력해주세요."></input>
          <input v-model="content" placeholder="내용을 입력해주세요."></input>
          <button>전송</button>
        </div>
        `,
        data() {
          return {
            nickname: '',
            content: '',
          };
        },
      });

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

html 파일을 열어보면 다음과 같은 화면이 나온다.

위의 소스에서 중요한 것은

input 엘리먼트에 v-model directive를 사용했고, nickname, content의 데이터 값과 바인드 시켰다는 것이다.

뷰 개발자도구를 이용하여 살펴보면 더 확실히 알 수 있다.

이제 이 form을 이용하여 방명록을 등록해보는 소스를 만들어보자.

완성본 소스는 아래와 같다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>TEST!!</title>
  </head>
  <body>
    <div id="app">
      <guest-book @guest-book-submit="addGuestBook"></guest-book>
      <div>
        <div v-if="!guestBooks.length">
          등록된 방명록이 존재하지 않습니다.
        </div>
        <ol>
          <li v-for="guestBook in guestBooks">
            닉네임 : {{guestBook.nickname}} / 내용 : {{guestBook.content}} / 날짜 :
            {{guestBook.date}}
          </li>
        </ol>
      </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
      // 앞에 선언해야 함
      Vue.component('guest-book', {
        template: `
  <div>
    <form @submit.prevent="submit">
      <input v-model="nickname" placeholder="닉네임을 입력해주세요." />
      <input v-model="content" placeholder="내용을 입력해주세요." />
      <input v-model.date="date" type="date" />
      <button>전송</button>
    </form>
  </div>
  `,
        data() {
          return {
            nickname: '',
            content: '',
            date: '',
          };
        },
        methods: {
          submit() {
            this.$emit('guest-book-submit', {
              nickname: this.nickname,
              content: this.content,
              date: this.date,
            });
          },
        },
      });

      var app = new Vue({
        el: '#app',
        data: {
          guestBooks: [],
        },
        methods: {
          addGuestBook(guestBook) {
            this.guestBooks.push(guestBook);
          },
        },
      });
    </script>
  </body>
</html>

this.$emit으로 이벤트 커뮤니케이션을 하는 것은 이전에 배워봤던 내용이다.

새로운 내용은 @submit.preventv-model.date인데

@submit.prevent는 directive 내부에 preventDefault() 함수를 자동으로 호출하는 기능이 있다.

preventDefault() 함수란 것은 submit을 할 때 기본 HTML5 스펙에서는 form을 제출하며 form에 action으로 지정된 URL로 이동하게 되는데 그러한 기본 동작을 막겠다는 의미이다.

그래서 @submit.prevent를 사용하면 페이지 이동을 하지 않게 된다.

Vue.js 공식 문서에서 이벤트 핸들링 페이지를 보면 아래와 같은 내용이 자세히 나와있다.

<!-- 클릭 이벤트 전파가 중단됩니다 -->
<a v-on:click.stop="doThis"></a>

<!-- 제출 이벤트가 페이지를 다시 로드 하지 않습니다 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 수식어는 체이닝 가능합니다 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 단순히 수식어만 사용할 수 있습니다 -->
<form v-on:submit.prevent></form>

<!-- 이벤트 리스너를 추가할 때 캡처모드를 사용합니다 -->
<!-- 즉, 내부 엘리먼트를 대상으로 하는 이벤트가 해당 엘리먼트에서 처리되기 전에 여기서 처리합니다. -->
<div v-on:click.capture="doThis">...</div>


<!-- event.target이 엘리먼트 자체인 경우에만 트리거를 처리합니다 -->
<!-- 자식 엘리먼트에서는 안됩니다 -->
<div v-on:click.self="doThat">...</div>

v-model.datev-model에서 타입을 지정할 수 있다는 것을 알려주기 위해 넣어봤다.

사실 date가 당연히 있는 줄 알고 당당하게 v-model.date를 적었지만

사실 v-model.date는 지원하지 않는 것 같다.

이 내용도 공식문서에서 폼 입력 바인딩 페이지를 보면 자세히 나와있다.

수식어 부분을 보면 자세히 나와있다.

profile
풀스택 웹개발자로 일하고 있는 Jake Seo입니다. 주로 Jake Seo라는 닉네임을 많이 씁니다. 프론트엔드: Javascript, React 백엔드: Spring Framework에 관심이 있습니다.

0개의 댓글