본문 바로가기
frontend/vue

[Hoon] Vuejs 강의 - 반복문 - 리스트 렌더링

by 훈즈 플로거 2020. 5. 11.

반복문 - 리스트 렌더링

https://kr.vuejs.org/v2/guide/list.html

v-for로 엘리먼트에 배열 매핑하기

v-for 디렉티브를 사용하여 배열을 기반으로 리스트를 렌더링 할 수 있습니다.
v-for 디렉티브는 item in items 형태로 특별한 문법이 필요합니다. 여기서 items는 원본 데이터 배열이고 item은 반복되는 배열 엘리먼트의 별칭 입니다.

#기본 사용방법

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<ul id="app">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
var vm = new Vue({
  el: '#app',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

v-for 블록 안에는 부모 범위 속성에 대한 모든 권한이 있습니다. v-for는 또한 현재 항목의 인덱스에 대한 두 번째 전달인자 옵션을 제공합니다.

<ul id="app">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
var app = new Vue({
  el: '#app',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

in 대신에 of를 구분자로 사용할 수 있습니다.

v-for와 객체

v-for를 사용하여 객체의 속성을 반복할 수도 있습니다.

<ul id="app" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
new Vue({
  el: '#app',
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }
})

키에 대한 두번째 전달 인자를 제공할 수도 있습니다.

<div id="app">
  <div v-for="(value, name) in object">
    {{ name }}: {{ value }}
  </div>
</div>

그리고 또 인덱스도 제공합니다

<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>

Maintaining State

Vue에서 개별 DOM 노드들을 추적하고 기존 엘리먼트를 재사용,
재정렬하기 위해서 v-for의 각 항목들에 고유한 key 속성을 제공해야 합니다.
key에 대한 이상적인 값은 각 항목을 식별할 수 있는 고유한 ID

<div v-for="obj in object" v-bind:key="obj.name">
  {{ obj }}
</div>

객체나 배열처럼, 기본 타입(Primitive value)이 아닌 값을 키로 사용해서는 안됩니다. 대신 문자열이나 숫자를 사용하세요.

배열 변경 감지 - [기본]

#변이 메소드

Vue는 감시중인 배열의 변이 메소드를 래핑하여 뷰 갱신을 트리거합니다.

  • push() - The new item(s) will be added at the end of the array.
  • pop() - To remove the last element from the array.
  • shift() - To remove the first item of an array.
  • unshift() - To adds new items to the beginning of an array
  • splice() - To adds/removes items to/from an array, and returns the removed item(s).
  • sort() - To sorts the items of an array.
  • reverse() - To method reverses the order of the elements in an array.

#배열 대체 - [기본]

변이 메소드는 호출된 원본 배열을 변형합니다. 이와 비교하여 변형을 하지 않는 방법도 있습니다. 바로 filter(), concat() 와 slice() 입니다. 이 방법을 사용하면 원본 배열을 변형하지 않고 항상 새 배열을 반환합니다.

<ul id="app">
  <div v-for="item in items">    
    {{ item.message }}
  </div>  
  <p>
  <button v-on:click="applyFilter">적용</button>
  </p>
</ul>
new Vue({
  el: '#app',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  },
  methods: {
  	applyFilter: function(){
    	this.items = this.items.filter(function(item){
      	return item.message.match(/Foo/)
      })
    }
  }
})

#주의 사항 - [기본]

JavaScript의 제한으로 인해 Vue는 배열에 대해 다음과 같은 변경 사항을 감지할 수 없습니다.

  1. 인덱스로 배열에 있는 항목을 직접 설정하는 경우, 예: vm.items[indexOfItem] = newValue
  2. 배열 길이를 수정하는 경우, 예: vm.items.length = newLength
<ul id="app">
  <div v-for="item in items">    
    {{ item }}
  </div>  
</ul>
var vm = new Vue({
  el: '#app',
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // reactive하지 않음
vm.items.length = 2 // reactive하지 않음

 

두번째 배열을 x 로 바꾸거나, 배열의 길이를 2개로 줄여도 반응하지 않습니다. Vue 에 직접 set 을 하거나, 해당 배열을 splice 하는 방법으로 해결할 수 있습니다.

  1. 인덱스로 배열에 있는 항목을 직접 설정
// Vue.set
//Vue.set(vm.items, indexOfItem, newValue)
Vue.set(vm.items, 1, 'x')

// Array.prototype.splice
//vm.items.splice(indexOfItem, 1, newValue)
vm.items.splice(1,1,'x')
  1. 배열 길이를 수정
//vm.items.splice(newLength)
vm.items.splice(2)

vm.items.length = 2
vm.$set(vm.items, 1, 'x')

필터링 / 정렬 된 결과 표시하기 - [기본]

원본 데이터를 실제로 변경하거나 재설정하지 않고 배열의 필터링 된 버전이나 정렬된 버전을 표시해야 할 필요가 있습니다. 이 경우 필터링 된 배열이나 정렬된 배열을 반환하는 계산된 속성(computed)을 만들 수 있습니다.

<ul id="app">
 <li v-for="n in evenNumbers">{{ n }}</li>  
</ul>
new Vue({
    el: '#app',
    data: {
        numbers: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
        evenNumbers: function () {
            return this.numbers.filter(function (number) {
                return number % 2 === 0
            })
        }
    }
})

계산된 속성을 실행할 수 없는 상황(예: 중첩 된 v-for 루프 내부

  • 이중 루프의 내부 루프) )에서는 다음 방법을 사용할 수 있습니다.
<div id="app">
<ul v-for="set in sets">
  <li v-for="n in even(set)">{{ n }}</li>
</ul>
</div>
new Vue({
    el: '#app',
    data: {
        sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
    },
    methods: {
        even: function (numbers) {
            return numbers.filter(function (number) {
                return number % 2 === 0
            })
        }
    }
})

Range v-for - [기본]

v-for 는 숫자를 사용할 수 있습니다.

<div id="app"> <span v-for="n in 10">{{ n }} </span> </div>
var vm = new Vue({
  el: '#app',
  data: {  
  }
})

v-for 템플릿 - [기본]

template 태그를 사용해 여러 엘리먼트의 블럭을 렌더링 할 수 있습니다.

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
  </template>
</ul>
var vm = new Vue({
  el: '#app',
  data: {  
  	items : [
    	{ msg : 'messag 1'},
      { msg : 'messag 2'},
      { msg : 'messag 3'},
    ]
  }
})

v-for 와 v-if - [기본]

동일한 노드에 두가지 모두 있다면, v-for가 v-if보다 높은 우선순위를 갖습니다. 즉, v-if는 루프가 반복될 때마다 실행됩니다. 이는 일부 항목만 렌더링 하려는 경우 유용합니다.

<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>
new Vue({
  el: '#app',
  data: {
    todos: [
      {
        id: 1,
        title: 'Do the dishes',
      },
      {
        id: 2,
        title: 'Take out the trash',
      },
      {
        id: 3,
        title: 'Mow the lawn'
      }
    ]
  }
})

위 방법 대신 실행을 조건부로 하는 것이 목적이라면 래퍼 엘리먼트(또는 template)를 사용해야 합니다.

<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>

bit.ly/3fXOzon

 

인프런 인강 55%할인 쿠폰 - 커피한잔으로 Vue.js 핵심 강의!

인프런 인터넷 강의 55% 할인 쿠폰 - 커피한잔(5000원)으로 배우는 Vue.js 핵심 강의! 모바일 환경에서도 강의를 수강할 수 있도록 강의가 많이 개선되었습니다. 인프런 인터넷 강의 선착순 100명 55% �

plogger.tistory.com

bit.ly/2TtRHis

 

[Vue.js 입문] 초보 실전 웹앱 개발 - 1부 : vue 개념 ~ 핵심 - 인프런

이 강의를 수강하시면 Vue.js 와 관련된 기본적인 개념부터 Real 웹앱 개발을 해 볼 수 있습니다. 이 강의는 1부 기본기 이며, 2부와 3부를 통해서 실제 Real 웹앱을 구현해 보도록 하겠습니다. 초급 ��

www.inflearn.com

 

댓글0