국비교육과정 정리/최종프로젝트

[Vue] 데이터 핸들링(Data Handling)

백설마을꿀단지 2023. 3. 6.

1. String 데이터 핸들링

String 타입의 데이터는 {{ }} 를 이용해서 다룬다. <script> 에서 key 와 value를 작성하고, <template>에서 {{ }} 사이에 key를 작성하면 자동으로 값이 대입된다.

<template>
<div>
    <h1>Hello {{userName}}</h1>
    <p>{{ message }}</p>
</div>
</template>

<script>
export default {
  data () {
return {
    userName: 'john Doe',
    message: 'Welcome to Vue World',
    arr: [],
    obj: {}
  }
}
}
</script>

 


2. DOM 핸들링

<script>에서 값을 HTML태그(DOM)으로 작성하여 {{ }}을 이용해 호출하면 DOM으로 인식되는 것이 아니라 문자열로 인식된다. 그러므로 DOM으로 인식시키고자 한다면 {{ }}이 아닌 v-html 속성을 이용한다.

<template>
  <div>
    <div>{{ htmlString }}</div>
    <div v-html="htmlString"></div>
  </div>
</template>

<script>
export default {
  components: {},
  data() {
    return {
      htmlString: '<p style="color:red">빨간색 문자</p>'
    }
  }
}
</script>

 


3. v-model 속성을 이용한 데이터 핸들링

 

1) input 데이터 핸들링

Vue.js 에서는 input의 name, id를 사용하지 않고도 양방향 바인딩이 가능하다.

v-model 속성을 이용하면 <script>에 작성된 key의 값이 자동으로 input 요소의 value 속성값으로 대입된다.

또한 사용자가 데이터를 입력할 시 자동으로 입력된 값이 <script>의 값으로 대입되는 양방향 데이터바인딩이 가능하다.

{{ }} 에서 key 값들의 연산도 가능하다. 하지만 위 그림을 확인해보면 20 + 10 의 결과가 30이 아닌 2010으로 나타난 것을 볼 수 있다. 그 이유는 input type:text 로 입력을 받았기 때문에 자동으로 문자열 데이터로 삽입되었기 때문이다. 그렇기 때문에 형변환이 필요한데 단순하게 v-model.numer 로 속성을 주면 정수형 데이터로 자동 형변환된다.

<template>
<div>
  <input type="text" v-model="userId">
  <button @click="myFunction"> 클릭 </button>
  <button @click="changeData">변경</button>
  <br/>
  <input type="text" v-model="num1"> +
  <input type="text" v-model="num2"> =
  <span>{{ num1 + num2 }}</span>
  <br/>
  <input type="text" v-model.number="num3"> +
  <input type="text" v-model.number="num4"> =
  <span>{{ num3 + num4 }}</span>
</div>
</template>

<script>
export default {
  data() {
    return {
      userId: '안녕',
      num1: 0,
      num2: 0,
      num3: 0,
      num4: 0
    }
  },
  methods: {
    myFunction () {
      console.log(this.userId)
    },
    changeData () {
      this.userId = '변경'
    }
  }

}
</script>

 

2) select 데이터 핸들링

select 요소에서도 v-model 의 양방향 데이터 바인딩을 활용할 수 있다. 사용자가 선택한 option의 값이 자동으로
select요소의 value값<script>의 value 값으로 대입된다.

<template>
  <div>
    <select v-model="selectedCity">
      <option value=""></option>
      <option value="02">서울</option>
      <option value="051">부산</option>
      <option value="031">인천</option>
    </select>

    <div> 선택된 도시번호: <span>{{ selectedCity }}</span></div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      selectedCity: '02'
    }
  }
}
</script>

 

3) checkbox 데이터 핸들링

v-model 속성을 사용해 input과 select의 데이터핸들링은 값을 문자열로 받았지만, checkbox 타입은 값이 여러 개가 선택될 수 있기 때문에 <script>에서 key의 값을 배열로 선언해야 한다.

input 태그의 value값과의 양방향 데이터바인딩이 이루어지는 것이 아니라 checked 속성을 인식 후 value 값을 가져와 배열에 집어넣는 형식이다.

앞서 vue.js 에서 id를 활용하지 않아도 된다하였는데, 여기서는 label 태그와 연동을 위해 id 속성을 사용하였다.

tip) <script>에 값을 미리 작성해놓으면 checked 속성을 준 것과 같은 효과를 지닌다.

 

 

4) radio 데이터 바인딩

radio는 하나의 선택만 가능하므로 <script>에서 key의 값을 배열이 아닌 문자열로 선언한다. 마찬가지로 v-model 속성을 이용해서 양방향 데이터바인딩을 한다.

<template>
  <div>
    <div>
      <input type="radio" name="" id="html" value="HTML" v-model="favoriteLang">
      <label for="html">HTML</label>
    </div>
    <div>
      <input type="radio" name="" id="css" value="CSS" v-model="favoriteLang">
      <label for="css">CSS</label>
    </div>
    <div>
      <input type="radio" name="" id="js" value="JavaScript" v-model="favoriteLang">
      <label for="js">JavaScript</label>
    </div>

    <div>
      선택한 언어 : {{ favoriteLang }}
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      favoriteLang: ''
    }
  }
}
</script>

 


4. v-bind를 이용해 요소의 속성에 데이터 바인딩하기

HTML 속성인 id, class, style 등에 대해 데이터를 연결할 때는 v-bind 를 이용한다. v-bind는 전달인자로 연결하려는 속성을 지정해주면 되고 v-bind를 생략하고   :   만 작성하여 간편하게 사용할 수도 있다.

cf) img 요소의 속성인 src 에도 :src 속성을 이용해서 데이터를 바인딩시킬 수 있다.

tip) 속성값에 true / false에 따른 활성화, 비활성 조건식을 작성할 수도 있다.

 

<template>
  <div>
    <input type="text" name="" id="" v-model="userId" readonly>
    <input type="text" name="" id="" v-bind:value="userId" readonly>
    <input type="text" name="" id="" :value="userId" readonly>
	<br>
    <img :src="imgSrc" alt="" style="width:100px, height:auto">
	<br>
    <input type="search" name="" id="" v-model="text1">
    <button :disabled="text1 === ''">조회</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      userId: 'aaa123',
      imgSrc: 'https://ssl.pstatic.net/melona/libs/1436/1436446/e07bcc3e1eb10664b123_20230228112642935.jpg',
      text1: ''
    }
  }
}
</script>

 


5. v-for 속성을 이용한 반복문 활용

v-for를 이용해서 배열을 기반으로 리스트를 랜더링시킬 수 있다. item in items 형태의 문법이 사용되며 items는 원본 데이터배열, item은 반복되는 배열 엘리먼트의 별칭을 뜻한다.
v-for 속성을 사용하기 위해서는 :key 속성도 작성해야하며 :key 속성의 값으로는 엘리먼트를 구분지을 수 있는 고유값이 들어가야 한다. 만약 배열 내에 고유값이 존재하지 않는다면 (item, index) in items 의 문법으로 index라는 고유값을 생성하여 :key 속성에서 사용할 수 있다.

<template>
  <div>
    <div>
      <table>
        <thead>
          <tr>
            <td>
              <th>제품번호</th>
              <th>제품명</th>
              <th>가격</th>
              <th>주문수량</th>
              <th>합계</th>
            </td>
          </tr>
        </thead>
        <tbody>
        <!--v-for 를 사용해 테이블을 간단하게 생성할 수 있다.-->
          <tr :key="drink.drinkId" v-for="drink in drinkList">
            <td>{{ drink.drinkName }}</td>
            <td>{{ drink.price }}</td>
            <td>{{ drink.qty }}</td>
            <td><input type="number" v-model="drink.qty"></td>
            <td>{{ drink.price * drink.qty }}</td>
          </tr>
          
          <!-- 
          :key 속성의 값을 배열의 고유값이 아닌 index를 생성하여 사용할 경우
          <tr :key="index" v-for="(drink,index) in drinkList"></tr>
          -->
          
        </tbody>
      </table>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      drinkList: [
        {
          drinkId: '1',
          drinkName: '코카콜라',
          price: 700,
          qty: 1
        },
        {
          drinkId: '2',
          drinkName: '사이다',
          price: 500,
          qty: 1
        },
        {
          drinkId: '3',
          drinkName: '오렌지주스',
          price: 1200,
          qty: 1
        }
      ]
    }
  }
}
</script>

 


6. v-bind를 이용한 class 다루기

v-bind와 boolean을 활용해서 마치 토글처럼 class 속성을 다룰 수 있다.

key : value 의 형태에서 value 값이 true일 경우에만 클래스가 적용되도록 하였다. 클래스 이름에 특수문자가 들어간다면 반드시 홑따옴표로 감싸주어야하며, 특수문자가없다면 그냥 작성해도 된다.

다음은 클릭 이벤트를 이용해서 토글방식으로 CSS가 들어가도록 만든 예시이다.

 

처음에는 text-red라는 클래스가 적용되어 빨간색 글씨이지만 클릭이벤트에 따라 토글처럼 text-red의 클래스가 사라지고 active 속성이 들어가도록 하였다.

<template>
  <div>
    <div :class="{ 'text-red' : hasError, active : isActive }">클래스 바인딩</div>
    <br>
    <button @click="clickHandler">버튼</button>

    <hr>
    <div :class="class2">클래스 바인딩2</div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      sampleData: '',
      isActive: false,
      hasError: false,
      class2: ['active', 'hasError']
    }
  },
  methods: {
    clickHandler () {
      this.hasError = !this.hasError
      this.isActive = !this.isActive
    }
  }
}
</script>

<style scoped>
  .active {
    background-color: black;
    color: white;
    font-weight: bold;
  }
  .text-red {
    color: red;
  }
</style>

 


7. CSS 데이터 바인딩

v-bind:style ( :style) 을 이용해서 css 속성도 바인딩시킬 수 있다.

 

select 요소를 이용해서 색상을 선택하면 해당 색상이 적용되도록 예시를 작성하였다.

적용 순서는 다음과 같다.

1) 최초 myStyle 을 통해 color:red 를 적용시킨다.

2) 선택된 option의 value를 v-model을 통해서 defaultColor에 대입시킨다.

3) onChange 이벤트를 통해 defaultColor의 값을 myStyle.color에 대입시킨다.

<template>
  <div>
    <div style="color:red; font-size:30px;">스타일 바인딩 : 글씨는 red, 폰트크기: 30px</div>
    <div :style="myStyle">스타일 바인딩 오브젝트 활용</div>

    <select v-model="defalutColor" @change="changeColor">
      {{ color }}
      <option value="">색상 선택</option>
      <option :value="color" 
      		  :key="index" 
              v-for="(color, index) in colorArr">
              {{ color }}
      </option>
    </select>
  </div>
</template>
<script>

export default {
  data () {
    return {
      defalutColor: '',
      colorArr: ['red', 'blue', 'green', 'orange', 'purple', 'aquablue', 'deepgreen'],
      myStyle: {
        color: 'red',
        fontSize: '30px'
      }
    }
  },
  methods: {
    changeColor () {
      this.myStyle.color = this.defalutColor
    }
  }
}
</script>

댓글