본문 바로가기
Web/Vue

Vue.js개념 총정리(4)_템플릿문법,데이터바인딩,데이터변화감지

by 나비와꽃기린 2021. 2. 1.

1.템플릿 문법이란

뷰의 템플릿은 HTML, CSS 등의 마크업속성과 뷰 인스턴스에서 정의한 데이터 및 로직들을 연결해 브라우저에서 볼 수 있는 형태의 HTML로 변환해주는 속성을 말한다.

여기서 템플릿 문법이란 뷰로 화면을 조작하는 '방법'을 의미하며 템플릿 문법은 크게 데이터바인딩과 디렉티브로 나뉜다.

1-1. 데이터바인딩

데이터바인딩은 뷰 인스턴스에서 정의한 속성들을 화면에 표시하는 방법으로 가장 기본적인 데이터 바인딩 방식은 콧수염괄호({{}}) 이며, 이외에 v-bind 속성이 있다.

new Vue({

   template : '<p>{{message}}</p>'

});

<p v-bind:id="bindId">id바인딩</p>

new Vue({

  data : {

      bindId : 'myId'

   }

})

 

라이브러리 내부적으로 template 속성에서 정의한 마크업 + 뷰 데이터를 가상 돔 기반의 render() 함수로 변환한다.

변환된 render() 함수는 최종적으로 사용자가 볼 수 있게 화면을 그리는 역할을 한다.

문법

설명

{{}}

뷰 인스턴스의 데이터를 HTML 태그에 연결하는 텍스트 삽입 방식이다.

v-bind

아이디,클래스,스타일 등의 HTML 속성 값에 뷰 데이터값을 연결할 때 사용한다.

 

1-2. 디렉티브

디렉티브는 뷰로 화면의 요소를 더 쉽게 조작하기 위한 문법으로 화면 조작에서 자주 사용되는 방식들을 모아 디렉티브형태로 제공한다.

HTML 태그안에 v- 접두사를 가지는 모든 속성들을 의미한다.

뷰의 데이터 값이 변경되었을 때 화면의 요소들이 리액티브하게 반응하여 변경된 데이터 값에 따라 갱신된다.

디렉티브이름

설명

v-if

지정한 뷰 데이터의 참,거짓에 따라 HTML 표시 여부를 선택한다.

v-for

지정한 뷰 데이터의 개수만큼 HTML 태그를 반복출력한다.

v-show

v-if와 유사하게 데이터의 참,거짓에 따라 HTML 표시 여부를 선택한다.

, v-if는 해당 태그를 완전삭제하지만 v-show css display:none; 처리를 하는것이 다르다.

v-bind

HTML 태그의 기본 속성과 뷰 데이터 속성을 연결한다.

v-bind 디렉티브를 줄여쓰는 방법 ex) v-bind:src :src 로 작성 가능

v-on

화면 요소의 이벤트를 감지하여 처리할 때 사용한다.

예를들어 v-on:click 은 해당 태그의 클릭 이벤트를 감지하여 특정 메소드를 실행시킨다.

v-on 디렉티브를 줄여쓰는 방법 ex) v-on:click  @click 로 작성가능 

v-model

form 태그에서 주로 사용되는 속성이다.

form에 입력한 값을 뷰 인스턴스의 데이터와 즉시 동기화한다.

화면에 입력된 값을 저장하여 서버에 보내거나 watch와 같은 고급 속성을 이용하여 추가 로직을 수행할 수 있다.

<input>,<select>,<textarea> 태그에만 사용할 수 있다.

v-text,{{}}

태그 문자열을 HTML 인코딩하여 나타내기 때문에 화면에 태그 문자열이 그대로 나타난다.

v-html

<sciprt> 태그를 그대로 바인딩하여 XSS에 취약. v-text를 사용하는것이 안전하다.

 

이 외, 다른 디렉티브에 대한 상세설명은 공식문서를 보고 참고하도록 하자.

공식문서https://vuejs.org/v2/guide/forms.html#Text

 

 

{{}}표현식이 화면에 잠깐 나타났다가 사라질때가 있는데 보이지않게 처리하기 위한 디렉티브로 v-cloak이 있다.

<style>

[v-cloak] :{display:none;}

</style>

 

 

 

<!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>Document</title>

</head>

<body>

  <div id="app">

    <p v-bind:id="uuid" v-bind:class="name">{{ num }}</p>

    <!-- <p id="abc1234">{{ num }}</p> -->

    <p>{{ doubleNum }}</p>

    <div v-if="loading">

      Loading...

    </div>

    <div v-else>

      test user has been logged in

    </div>

    <div v-show="loading">

      Loading...

    </div>

    <input type="text" v-model="message">

    <p>{{ message }}</p>

  </div>

 

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>

    new Vue({

      el: '#app',

      data: {

        num: 10,

        uuid: 'abc1234',

        name: 'text-blue',

        loading: true,

        message: ''

      },

      computed: {

        doubleNum: function() {

          return this.num * 2;

        }

      }

    })

  </script>

</body>

</html>

<!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>Document</title>

</head>

<body>

  <div id="app">

    <button v-on:click="logText">click me</button>

    <input type="text" v-on:keyup.enter="logText"><!--이벤트모디파이어 .으로 접근 enter시에만 해당메소드를 실행-->

    <button>add</button>

  </div>

 

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>

    new Vue({

      el: '#app',

      methods: {

        logText: function() {

          console.log('clicked');

        }

      }

    })

  </script>

</body>

</html>

1-3. watch 속성 vs computed 속성

Vue에서 속성이 변경될 때 변화에 대응하고 싶을 때 watch 속성 및 computed을 사용할 수 있다.

 

참조하고 있는 값이 변경될 때마다 정의된 계산식에 따라 값을 출력하는 computed와 다르게, watch는 값이 변경될 때 실행되는 함수를 지정할 수 있다.

computed가 계산된 값을 출력하는 용도라면 watch는 어떤 조건이 되었을 때 함수를 실행시키기 위한 트리거로서 사용할 수 있다는 의미이다.

 

데이터 변화를 감지하여 특정 로직이 샐행되는 watch의 속성에 따라, watch는 매번 실행되기 부담스러운 로직이나 상대적으로 처리시간이 긴 데이터요청작업 등을 처리하는데 있어서 적합하며

텍스트연산이나 validation 체크 같은 기능은 computed가 적합하다.

<!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>Document</title>

</head>

<body>

  <div id="app">

    {{ num }}

  </div>

 

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>

    new Vue({

      el: '#app',

      data: {

        num: 10

      },

      computed: {

        doubleNum: function() {

          return this.num * 2;

        }

      },

      watch: {

        num: function(newValue, oldValue) {

          this.fetchUserByNumber(newValue,oldValue);

        }

      },

      methods: {

        fetchUserByNumber: function(newValue,oldValue) {

           console.log(newValue,oldValue);

          axios.get(newValue);

        }

      }

    });

  </script>

</body>

</html>

 

      }

    })

  </script>

</body>

</html>

 

다음과 같이 computed 속성을 사용하여 클래스 코드를 작성할 수도 있다.

템플릿표현식에 작성하는것이 아닌 스크립트단으로 소스를 내려 직관적으로 표현할 수도 있다.

<!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>Document</title>

  <style>

  .warning {

    color: red;

  }

  </style>

</head>

<body>

  <div id="app">

    <p v-bind:class="cname">Hello</p>

    <p v-bind:class="{ warning: isError}">Hello</p> <!--warning이라는 클래스를 조건에 따라 출력여부를 판단-->

                                                    <!--isError 값이 true 빨간색 스타일 적용-->

    <p v-bind:class="errorTextColor">Hello</p> <!-- { warning: isError} 계산식을 errorTextColor 텍스트로 대체 (computed 속성 사용) -->

  </div>

   

  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

  <script>

    new Vue({

      el: '#app',

      data: {

        // cname: 'blue-text',

        isError: true

      },

      computed: {

        errorTextColor: function() {

          return this.isError ? 'warning' : null;

        }

      }

    });

  </script>

</body>

</html>

댓글0