v-bind, v-on과 v-model

v-bind

html 요소에 속성(뷰 인스턴스 안의 데이터)을 바인딩할 때 사용한다. 서버를 거치지 않고 view 영역에서 처리하게 된다. 만약 데이터가 변경된다면 동적으로 바로 html의 속성이 변화된다.

마치 모델의 데이터가 변경될 때 자동으로 뷰의 데이터를 업데이트시켜주는 단방향

v-bind로 속성 바인딩하기

input이 있고 그 안에 텍스트가 입력되지 않은 경우 전송 버튼을 disabled한다. 이를 위해 disabled 속성을 바인딩한다.

// BasicView.vue

<template>
  <div>
    <input type="text" v-model="textValue" />
    <button
      type="button"
      **:disabled="textValue == ''"**
      @click="printText"
    >
      Search
    </button>
  </div>
</template>
<script>
export default {
  name: 'BasicView',
  components: {},
  data() {
    return {
      textValue: '',
    }
  },
  methods: {
    printText() {
      console.log(this.textValue)
      this.textValue=''
    },
  },
}
</script>

v-bind로 HTML 클래스 바인딩하기

클래스를 동적으로 토글하기 위해 v-bind:class에 객체를 전달한다.

아래의 app-2 요소 안의 div는 일단 static 클래스를 가지고 있다.

//html
<div id="app-2">
  <div
    class="static"
    v-bind:class="{active: isActive, 'text-danger': hasError}"
  ></div>
</div>
// js
var app2 = new Vue({
  el: '#app-2',
  data: {
    isActive: false,
    hasError: true
  }
})

이 상황에서 해당 요소는

<div class="static text-danger"></div>

와 같이 렌더링된다.

한꺼번에 더 많은 클래스를 적용시키기 위해서 배열 구문을 사용해서 클래스를 바인딩할 수 있다.

<div id="app">
  <div v-bind:class="[isActive ? activeClass : '', errorClass]">DIV</div>
</div>

or

<div id="app">
  <div v-bind:class="[{ activeClass: isActive }, errorClass]">DIV</div>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    activeClass: 'active',
    errorClass: 'text-danger',
    isActive: false,
  },
})

위의 요소는 밑과 같이 렌더링된다.

<div class="text-danger">DIV</div>

인라인 스타일 바인딩하기

v-bind:style로 인라인 스타일을 바인드할 수 있다.

<div id="app-2">
  <p **v-bind:style="styleObject"**>Inline Style Changed</p>
  <button v-on:click="handleChangeColor">Change Color</button>
</div>
// js
var app2 = new Vue({
  el: '#app-2',
  data: {
    styleObject: {
      color: 'red',
      fontSize: '25px',
    },
  },
  methods: {
    handleChangeColor: function () {
      var val = this.styleObject.color
      this.styleObject.color = val === 'red' ? 'blue' : 'red'
    },
  },
})

v-on

해당 요소에 발생하는 이벤트를 뷰 인스턴스 안의 로직과 연결시켜서 이벤트 핸들링을 할 수 있도록 해 준다. 즉, Vue의 이벤트 리스너 역할을 해 준다.

// html
<div id="app">
  <button v-on:click="greet">Greet</button>
</div>
// js
var vm = new Vue({
  el: '#app',
  data: {
    name: 'Vue.js'
  },
  methods: {
    greet: function(event){
      alert(`Hello, ${this.name}!`)

      if(event) {  // event 객체 역시 불러올 수 있다.
        console.log(event.target.tagName)
      }
    }
  }
})

change 이벤트

해당 값이 변화할 때마다 호출되는 이벤트이다. select, radio 등에 활용할 수 있다.

<template>
  <div>
    <select v-model="city" @change="changeSelect">  <!--city의 값이 변화될 때마다 호출되는 이벤트-->
      <option value="서울">서울</option>
      <option value="부산">부산</option>
      <option value="제주">제주</option>
    </select>
  </div>
</template>

<script>
export default {
  name: 'BasicView',
  components: {},
  data() {
    return {
      city: "서울"
    }
  },
  methods: {
    changeSelect() {
      console.log(this.city)
    }
  }
}
</script>

v-model

Form 요소에서 해당 데이터를 양방향 바인딩으로 바인딩할 때 사용한다. v-bind와 v-on을 합친 기능이라 생각하는 것이 편하다.

기존의 리액트에서 만약 input 창에 입력되는 데이터를 바로 나타내주려면 input 요소에 이벤트 핸들러를 달고, event 객채의 target.value를 가져와서 state와 연결해서 나타내주어야 했다. 즉, 리액트는 단방향 바인딩이기 때문에 뷰에서 변경된 데이터를 모델에 업데이트 해 주기 위해 이벤트를 사용해야 했다.

v-model을 사용하면 따로 이벤트를 설정해주지 않아도 뷰 데이터가 바뀌면 바로 모델로 업데이트가 가능하다.

<div id="app">
  <input v-model="message" placeholder="텍스트를 입력하세요"/>
  <p>{{message}}</p>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    message: ''
  },
})

따로 v-on을 사용해서 이벤트를 핸들링해주지 않았다. 그럼에도 input에서 message 데이터를 변경하면 그것이 바로 모델에 업데이트되고, 그 업데이트된 데이터가 {{}}mustach를 통해 뷰에 또 바로 보여주게 된다.

이는 input 요소에 v-bind로 뷰 인스턴스 안의 데이터를 바인딩하고, 뷰 인스턴스에 event를 인자로 받아 해당 데이터를 event.target.value로 바꿔주는 메서드를 선언한 다음, 해당 요소에 v-on으로 묶어주는 방식으로 대체할 수도 있다.

밑의 방식은 한국어, 일본어, 중국어와 같은 IME 입력에 대해서 처리해줄 때 사용한다.

<div id="app">
  <input v-model="message" placeholder="텍스트를 입력하세요" />
  <p>{{message}}</p>
  <input
    **v-on:input="updateMessage"**   // input 이벤트 핸들러
    **v-bind:value="boundMessage"**  // input.value(html 요소의 속성)
    placeholder="텍스트를 입력하세요"
  />
  <p>{{boundMessage}}</p>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    message: '',
    **boundMessage**: '',
  },
  methods: {
    **updateMessage**: function (**event**) {
      this.boundMessage = **event.target.value**
    },
  },
})

v-for과 함께하는 동적 렌더링

select에서 v-for를 사용해 동적으로 렌더링이 가능하다.

<div id="app">
  <select v-model="selected">
    <option v-for="option in options" v-bind:value="option.value">
      {{option.text}}
    </option>
  </select>
  <span>Selected: {{selected}}</span>
</div>
var app = new Vue({
  el: '#app',
  data: {
    selected: 'A',
    options: [
      {text: 'One', value: 'A'},
      {text: 'Two', value: 'B'},
      {text: 'Three', value: 'C'},
    ]
  },
})