[VueJS] Vuejs 템플릿 문법

Cover image

Vue.js 템플릿 문법

뷰의 템플릿 문법이란 뷰로 화면을 조작하는 방법을 의미합니다. 템플릿 문법은 크게 데이터 바인딩디렉티브로 나뉩니다.

데이터 바인딩

데이터 바인딩이란 뷰 인스턴스에서 정의한 속성들을 화면에 표시하는 방법입니다. 가장 기본적인 데이터 바인딩 형식은 Mustache Tag입니다.

아래는 그 예제입니다,

<div>{{ message }}</div>
new Vue({
  data: {
    message: 'Hello Vue.js',
  },
})

해당 코드는 div 태그에 {{}}(Mustache Tag)를 통해 뷰 인스턴스의 message속성을 연결해서 화면에 Hello Vue.js가 출력되게 됩니다.

데이터를 바꾸는 경우에는 computed를 사용하는 것이 좋습니다.


디렉티브

디렉티브는 뷰로 화면의 요소를 더 쉽게 조작하기 위한 문법입니다. 화면 조작에서 주로 사용하는 방식들을 모아서 디렉티브 형태로 제공합니다. 예를 들어 아래와 같이 특정 속성 값에 따라 화면의 영역을 표시하거나 표시하지 않을 수 있습니다.

v-if 예제

아래의 예시는 show의 속성값에 따라 Vue.js 텍스트가 출력되거나 되지 않습니다.

<div>Hello <span v-if="show">Vue.js</span></div>
new Vue({
  data: {
    show: false,
  },
})

v-for 예제

또 다른 예시는 v-for 디렉토리를 통해서 데이터 속성의 개수만큼 화면의 요소를 반복하여 출력할 수 있습니다. 목록을 표현하는 경우 유용하게 사용가능합니다.

<ul>
    <li v-for:"item in items">{{item}}</li>
</ul>
new Vue({
  data: {
    items: ['shirts', 'jeans', 'hats'],
  },
})

이와 같이 사용할 수 있습니다.

v-on 예제 및 methods 속성

<div id="app">
  <button v-on:click="logText">click me</button>
  <input type="text" v-on:keyup="logText" />
  <!-- <input type="text" v-on:keyup.enter="logText">-->
  <!-- .enter를 붙이면 modified(엔터 친 경우) 된 경우만 적용 -->
</div>
new Vue({
  el: '#app',
  methods: {
    logText: function() {
      console.log('clicked')
    },
  },
})

해당 예제는 "click me"를 클릭시 console 창에 clicked 메세지가 발생합니다. input에 v-on:keyup을 줌으로써, 입력하고 키보드를 떼는 순간 이벤트가 발생합니다. keyup.enter를 붙이게 되면 modified된 경우에만 적용하게 됩니다.

이예 대한 실제 코드는 아래에 적어놓았습니다.

그 외의 디렉티브

주로 사용되는 디렉티브는 다음과 같습니다.

  • v-if / v-else
  • v-for
  • v-on
  • v-model
  • v-show (v-if 와 다르게 html element에 남아있습니다.)

이 외에도 다양한 문법을 알아야하는 경우에는 일일히 그에 따른 개념을 외울수는 없기 때문에 공식 문서에서 보면서 찾아야합니다.

공식 문서에 대한 링크는 다음과 같습니다.


Method

뷰 메서드는 특정 기능 별로 묶을 수 있는 자바스크립트 함수를 의미합니다. 메서드는 뷰 템플릿의 버튼 이벤트 처리부터 HTTP 통신까지 다양한 성격의 코드로 구성됩니다.

Method 코드 형식

일반적인 메서드 코드의 형식은 아래와 같습니다.

new Vue({
  methods: {
    // ...
  },
})

Method 예시 - 1

기본적인 버튼 클릭 메서드입니다.

<button v-bind:click="clickButton">click me</button>
new Vue({
  methods: {
    clickButton() {
      alert('clicked')
    },
  },
})

해당 예시 코드는 click me를 클릭하면 경고창이 뜨고 알람이 발생합니다.

Method 예시 - 2

화면 조작 외에도 특정 로직을 담을 수도 있습니다.

<button v-bind:click="displayProducts">Refresh</button>
new Vue({
  data: {
    products: [],
  },
  methods: {
    displayProducts() {
      this.fetchData()
      // ..
    },
    fetchData() {
      axios
        .get('/products')
        .then(function(response) {
          this.products = response.data
        })
        .catch(function(error) {
          alert(error)
        })
    },
  },
})

해당 코드에서 Refresh 버튼 클릭 시, displayProducts() 메서드가 실행되고, 이 메서드가 fetchData()를 호출합니다. 이런식으로 연결하게 되면, 특정 기능 별로 메서드를 분리할 수 있고 코드를 중복없이 사용할 수 있게 됩니다.


Computed

Computed 속성은 템플릿의 데이터 표현을 더 직관적이고 간결하게 도와주는 속성입니다.

코드의 예시는 다음과 같습니다.

<div>{{ reverseMessage }}</div>
computed: {
    reverseMessage() {
        return this.messgae.split(' ').reverse().join(' ');
    }
}

computed 장점

Computed 속성은 두가지의 장점이 있습니다,.

  • 코드의 가독성을 높여줍니다.
  • Computed 속성의 대상으로 정한 data 속성이 변했을 때 이를 감지하고 자동으로 다시 연산해줍니다.

computed 주의사항 1 - computed 속성은 인자를 받지않습니다.

아래는 잘못된 코드이며 정상적으로 동작하지 않습니다.

<div>{{ reverseMessage(false) }}</div>
computed: {
  reverseMessage(isReversed) {
    return isReversed ? this.message.split('').reverse().join('') : this.message;
  }
}

computed 주의사항 2 - HTTP 통신과 같이 컴퓨팅 리소스가 많이 필요한 로직은 정의하지 않습니다.

비싼 비용의 로직은 작성하지 않습니다. 이는 watch나 method에 넣는 것이 적합합니다. 아래는 잘못된 코드입니다.

data: {
  message: ''
},
computed: {
  reverseMessage() {
    var vm = this;
    axios.get('/message').then(function(response) {
      vm.message = response.data;
    });
    return this.message.split('').reverse().join('');
  }
}

Watch

watch 속성은 특정 데이터의 변화를 감지해서 자동으로 특정 로직을 수행해주는 속성입니다.

코드 구현 형식은 다음과 같습니다.

new Vue({
  data() {
    return {
      message: 'Hello',
    }
  },
  watch: {
    message: function(value, oldValue) {
      console.log(value)
    },
  },
})

watch의 실용 문법은 아래와 같습니다.

watch 사용 방식 1 - watch 속성에 메서드 함수 연결

watch 대상 속상에 함수 대신에 메소드를 연결하는 예시입니다.

new Vue({
  data() {
    return {
      message: 'Hello',
    }
  },
  methods: {
    logMessage() {
      console.log(this.message)
    },
  },
  watch: {
    message: 'logMessage', // 대상 속성과 메서드 함수를 매칭합니다.
  },
})

watch 사용 방식 2 - 핸들러와 초기 실행 옵션

watch 대상 속성에 아래와 같이 handler()immediate 속성을 정의할 수 있습니다.

new Vue({
  data() {
    return {
      message: 'Hello',
    }
  },
  watch: {
    message: {
      handler(value, oldValue) {
        console.log(value)
      },
      immediate: true, // 컴포넌트가 생성되자마자 즉시 실행됩니다.
    },
  },
})

실제 코드

Computed vs Watch

공식 document를 보면 computedwatch property에 대한 이야기가 있습니다.

Vue는 Vue 인스턴스의 데이터 변경을 관찰하고 반응하는 watch 속성을 제공합니다. 다만, 다른 데이터 기반으로 변경할 필요가 있는 데이터의 경우에는 watch 속성 보다는 computed 속성이 좋습니다.

아래는 두 속성의 차이를 보여주는 코드입니다.

<div id="demo">{{ fullName }}</div>
var vm = new Vue({
    el: '#demo',
    data: {
        firstName: 'Foo',
        lastName: 'Bar',
        fullName: 'Foo Bar'
    },
    watch: {
        firstName: function (val) {
            this.fullName = val + ' ' + this.lastName;
        },
        lastName: fucntion (val) {
            this.fullName = this.firstName +  ' ' + val;
        }
    }
})

위는 watch 속성을 이용한 코드입니다. 명령형이며 코드를 반복합니다.

아래는 computed를 이용한 코드입니다.

var vm = new Vue({
    el: '#demo',
    data: {
        firstName: 'Foo',
        lastName: 'Bar',
    },
    computed; {
        fullName: function() {
            return this.firstName + ' ' + this.lastName;
        }
    }
})

Filter

뷰 필터는 화면에 표시되는 텍스트의 형식을 쉽게 변환해주는 기능입니다. 간단하게 단어의 대문자화부터 다국어, 국제 통화 표시 드으로 다양하게 사용할 수 있습니다.

필터 사용 방법

<div id="app">
  {{ message | capitalize }}
</div>
new Vue({
  el: '#app',
  data: {
    message: 'hello',
  },
  filters: {
    capitalize: function(value) {
      if (!value) return ''
      value = value.toString()
      return value.charAt(0).toUpperCase() + value.slice(1)
    },
  },
})

위 코드를 실행시키면 hello가 아닌 Hello 텍스트가 화면에 나오게됩니다.

필터 등록 패턴

filter 속성을 각 컴포넌트에 등록하는 방법도 있지만, 읿반적으로는 filter.js 파일을 별도로 분리해서 사용합니다.

// filters.js
export function capitalize() {
  // ..
}

export function translate() {
  // ..
}
// main.js
import Vue from 'vue'
import * as filters from 'filters.js'

Object.keys(filters).forEach(function(key) {
  Vue.filter(key, filters[key])
})

new Vue({
  // ..
})

다음과 같은 구조를 가지게 됩니다.


Form handling

폼(Form)은 웹 어플리케이션에서 가장 많이 사용되는 코드 형식입니다. 로그인이나 상품 결제 등 모든 곳에 사용자의 입력을 처리하는 폼이 필요합니다.

간단한 로그인 Form 에시

다음의 순서를 따라 구성할 수 있습니다.

예제 코드는 다음과 같습니다.

<form v-on:submit.prevent="loginUser">
  <div>
    <label for="email">Email</label>
    <input id="email" type="text" ref="email" />
  </div>
  <div>
    <label for="password">Password</label>
    <input id="password" type="password" ref="password" />
  </div>
  <div>
    <button type="submit">Login</button>
  </div>
</form>
new Vue({
  methods: {
    loginUser() {
      var email = this.$refs.email.value
      var password = this.$refs.password.value
      axios.post('/login', {
        email: email,
        password: password,
      })
    },
  },
})

이에 따른 설명은 아래의 원본 링크에서 더 자세히 볼 수 있습니다.