Vue 리스트 렌더링

YEZI🎐·2022년 11월 22일
0

Vue

목록 보기
14/45

리스트 렌더링

v-for와 배열

  • v-for 디렉티브를 사용하여 배열 기반으로 리스트를 렌더링
  • v-for 디렉티브는 item in items 형태로 특별한 문법이 필요
    in 대신 of를 구분자로 사용 가능
  • items : 원본 데이터 배열
    item : 반복되는 배열 엘리먼트의 별칭
<ul id="example-1">
  <li v-for="item in items" :key="item.message">
    {{ item.message }}
  </li>
</ul>

<div v-for="item of items"></div>
var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})
  • v-for 블록 안에는 부모 범위 속성에 대한 모든 권한이 있음
    (ex. item.message 처럼 사용하는 것을 말함)
  • v-for는 또한 현재 항목의 인덱스에 대한 argument 옵션(index) 을 제공
<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ index + item.message }}
  </li>
</ul>
var example2 = new Vue({
  el: '#example-2',
  data: {
    parentMessage: 'Parent',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

v-for와 객체

  • v-for 디렉티브를 사용하여 객체의 속성을 반복
<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      // value : 'How to do lists in Vue'
      // name  : title
      // index : 0
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }
})
  • 배열과 마찬가지로 객체도 argument 옵션(index) 제공
  • 값, 키, index도 사용 가능
<div v-for="(value, name) in object">
  {{ name + value }}
</div>
<div v-for="(value, name, index) in object">
  {{ index + name + value }}
</div>

Maintaining State

  • Vue가 v-for에서 렌더링된 엘리먼트 목록을 갱신할 때 기본적으로 in-place patch 전략 사용
  • 데이터 항복의 순서가 변경된 경우, 항목의 순서와 일치하도록 DOM 요소를 이동하는 대신
    Vue는 각 요소를 적절한 위치에 패치하고 해당 인텍스에서 렌더링할 내용을 반영하는지 확인함
  • Vue에서 개별 DOM 노드들을 추적하고 기존 엘리먼트를 재사용, 재정렬하기 위해서 v-for의 각 항목들에 고유한 key 속성을 제공해야 함
    이때, key값은 요소를 구별할 수 있는 unique 한 내용을 사용해야 함
<div v-for="item in items" v-bind:key="item.id">
  <!-- content -->
</div>

배열 변경 감지

변이 메소드

  • Vue는 감시 중인 배열의 변이 메소드를 래핑하여 뷰 갱신을 트리거
  • 변이 메소드는 호출된 원본 배열을 업데이트함
  • 변이 메소드 종류
    push(), pop(), shift(), unshift(), splice(), sort(), reverse()
example1.items.push({ message: 'Baz' })

배열 대체

  • 원본 배열을 업데이트 하지 않고 새 배열을 반환
  • 배열 업데이트를 하지 않는 작업을 할 때 사용
  • 배열 대체 메소드 종류
    filter(), concat(), slice()
example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})

주의사항

배열

JavaScript의 제한으로 인해 Vue는 배열에 대해 아래와 같은 변경 사항을 감지할 수 없음

  • 인덱스로 배열에 있는 항목을 직접 설정하는 경우
    (ex. vm.items[indexOfItem] = newValue)
  • 배열 길이를 수정하는 경우
    (ex. vm.items.length = newLength)
var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 반응하지 않음
// 해결 방법 : Vue.set, Array.prototype.splice, vm.$set
// 컴포넌트 안에서 쓸 때 : Vue.set = this.$set

vm.items.length = 2 // 반응하지 않음
// 해결 방법 : vm.items.splice(newLength)

객체

모던 JavaScript의 한계로 Vue는 속성 추가 및 삭제를 감지하지 못함
Vue는 이미 만들어진 인스턴스에 새로운 루트레벨반응형 속성을 동적으로 추가하는 것을 허용하지 않음

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a`는 반응형

vm.b = 2 // 나중에 추가된 `vm.b`는 반응형 X

// 해결 방법 1. Vue.set(object, propertyName, value)
// Vue.set(vm.someObject, 'b', 2)
// 컴포넌트 안에서 쓸 때 : Vue.set = this.$set

// 해결방법 2. Object.assign()
// this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

필더링 · 정렬 된 결과 표시

원본 데이터를 실제로 변경하거나 재설정하지 않고 배열의 필더링 된 버전이나 정렬된 버전을 표시해야 할 때 computed를 사용

  • computed를 사용하는 경우
<li v-for="n in evenNumbers">{{ n }}</li>
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}
  • computed를 사용할 수 없는 경우(중첩된 v-for) : methods 이용
<ul v-for="set in sets">
  <li v-for="n in even(set)">{{ n }}</li>
</ul>
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
    })
  }
}

v-for with a Range

v-for는 숫자를 사용할 수 있으며, 이 경우 템플릿을 여러 번 반복한다.

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

v-for 템플릿

템플릿 v-if와 마찬가지로, <template>태그를 사용해 여러 엘리먼트의 블럭을 렌더링한다.

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-forv-if

v-forv-if를 동시에 사용하는 것은 추천하지 않는다.
동일한 노드에 두 가지 모두 있다면,
v-forv-if보다 높은 우선 순위를 갖는다.
즉, v-if는 루프가 반복될 때마다 실행되며, 이는 일부 항목만 렌더링 하려는 경우 유용하다.

<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>

<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>
profile
까먹지마도토도토잠보🐘

0개의 댓글