목록 렌더링


Directory


v-for를 사용하여 배열을 요소 집합에 대응시키세요v-for 把一个数组对应为一组元素


我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名

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

结果:

1.jpg

v-for 块中,我们可以访问所有父作用域的属性。v-for 还支持一个可选的第二个参数,即当前项的索引。

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

结果:

2.jpg

你也可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:

<div v-for="item of items"></div>


v-for 里使用对象


你也可以用 v-for


We v-for 지시문을 사용하여 배열을 기반으로 목록을 렌더링할 수 있습니다. v-for 지시문에는 item in items 형식의 특수 구문이 필요합니다. 여기서 items는 소스 데이터 배열이고 item는 반복되는 배열 요소의

alias

입니다.

<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
3.jpg결과:

1.jpg

v-for 블록에서는 모든 상위 범위 속성에 액세스할 수 있습니다. v-for는 선택적인 두 번째 인수인 현재 항목의 인덱스도 지원합니다. 4.jpg

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

결과: 🎜🎜2.jpg🎜🎜in 대신 of를 구분 기호로 사용할 수도 있습니다. 이는 JavaScript 반복자의 구문에 더 가깝기 때문입니다: 🎜
<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>
🎜🎜🎜

🎜🎜v-for🎜


🎜에서 객체 사용 v-for를 사용하여 순회할 수도 있습니다. 객체의 속성입니다. 🎜
<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>
example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})
🎜결과: 🎜🎜🎜🎜🎜두 번째 매개변수를 속성 이름(즉, 키 이름)으로 제공할 수도 있습니다. 🎜
var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
🎜🎜🎜

세 번째 매개변수를 인덱스로 사용할 수도 있습니다:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

5.jpg

객체를 순회할 때 Object.keys()의 결과에 따라 순회되지만 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。


维护状态


当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个类似 Vue 1.x 的 track-by="$index"

这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性:

vm.$set(vm.items, indexOfItem, newValue)

建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。

不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。

更多 key attribute 的细节用法请移步至 key 的 API 文档


数组更新检测



变异方法 (mutation method)

Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

  • push()

  • pop()

  • shift()

  • unshift()

  • splice()

  • sort()

  • reverse()

你可以打开控制台,然后对前面例子的 items 数组尝试调用变异方法。比如 example1.items.push({ message: 'Baz' }) 그럴 수 없습니다

결과가 서로 다른 JavaScript 엔진에서도 일관됨을 보장합니다.


Maintenance state


Vue가 실행될 때 사용됩니다. 업데이트됨 v-for는 요소 목록을 렌더링할 때 기본적으로 "제자리에서 업데이트" 전략을 사용합니다. 데이터 항목의 순서가 변경되면 Vue는 데이터 항목의 순서와 일치하도록 DOM 요소를 이동하지 않지만 각 요소를 제자리에 업데이트하고 각 인덱스 위치에서 올바르게 렌더링되도록 합니다. 이는 Vue 1.x의 track-by="$index"와 유사합니다.

🎜이 기본 모드는 효율적이지만 🎜하위 구성 요소 상태 또는 임시 DOM 상태(예: 양식 입력 값)에 의존하지 않는 목록 렌더링 출력에만 적용됩니다🎜. 🎜🎜Vue가 각 노드의 ID를 추적하여 기존 요소를 재사용하고 재정렬할 수 있도록 힌트를 제공하려면 각 항목에 고유한 key 속성을 ​​제공해야 합니다. 🎜
vm.items.splice(newLength)
🎜권장 출력 DOM 콘텐츠를 탐색하는 것이 매우 간단하거나 성능을 얻기 위해 의도적으로 기본 동작에 의존하지 않는 한 v-for를 사용할 때 key 속성을 ​​제공할 수 있습니다. 🎜🎜Vue가 노드를 식별하는 일반적인 메커니즘이기 때문에 keyv-for에만 특별히 관련되지 않습니다. 가이드의 뒷부분에서 살펴보겠지만, 다른 용도도 있습니다. 🎜🎜🎜객체나 배열 등 기본이 아닌 유형의 값을 v-forkey로 사용하지 마세요. 문자열이나 숫자 값을 사용하세요. 🎜🎜 key 속성에 대한 자세한 사용법을 보려면 에 대한 API 문서입니다. 🎜🎜🎜🎜

🎜어레이 업데이트 감지🎜🎜


🎜🎜🎜

🎜🎜mutation method🎜🎜🎜🎜Vue는 청취된 배열의 변형 메소드를 래핑하므로 뷰 업데이트도 트리거합니다. 래핑된 메소드에는 다음이 포함됩니다: 🎜

  • 🎜push()🎜
  • 🎜 pop() 🎜
  • 🎜shift()🎜
  • 🎜unshift()🎜
  • 🎜splice()🎜
  • 🎜sort()🎜
  • 🎜reverse()🎜
🎜콘솔을 열고 이전 예의 items 배열에 대한 변형 메서드를 호출해 볼 수 있습니다. 예를 들어 example1.items.push({ message: 'Baz' })입니다. 🎜🎜🎜🎜🎜🎜🎜어레이 교체🎜🎜🎜

Mutation 메서드는 이름에서 알 수 있듯이 해당 메서드가 호출되는 원래 배열을 변경합니다. 이와 대조적으로 filter(), concat()slice()와 같은 변경되지 않는 메서드도 있습니다. 원래 배열을 변경하지 않고 항상 새 배열을 반환합니다. 비변환 접근 방식을 사용할 때 이전 배열을 새 배열로 바꿀 수 있습니다: filter()concat()slice() 。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的

你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。


注意事项

由于 JavaScript 的限制,Vue 不能检测以下数组的变动:

  1. 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue

  2. 当你修改数组的长度时,例如:vm.items.length = newLength

举个例子:

var vm = new Vue({
  data: {
    userProfile: {
      name: 'Anika'
    }
  }
})

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:

Vue.set(vm.userProfile, 'age', 27)

你也可以使用 vm.$set 实例方法,该方法是全局方法 Vue.set 的一个别名:

vm.$set(vm.userProfile, 'age', 27)

为了解决第二类问题,你可以使用 splice

Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})


对象变更检测注意事项


还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性。例如,对于:

<li v-for="n in evenNumbers">{{ n }}</li>

你可以添加一个新的 age 属性到嵌套的 userProfile 对象:

data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:

<li v-for="n in even(numbers)">{{ n }}</li>

有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign()_.extend()

data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

이렇게 하면 Vue가 기존 DOM을 삭제하고 전체 목록을 다시 렌더링하게 된다고 생각할 수도 있습니다. 다행히도 그렇지 않습니다. Vue는 DOM 요소의 재사용을 극대화하기 위해 몇 가지 스마트한 경험적 방법을 구현하므로 원래 배열을 동일한 요소가 포함된 배열로 바꾸는 것은 매우 효율적인 작업입니다.


참고

🎜JavaScript 제한으로 인해 Vue < 다음 배열의 변경 사항은 Strong>감지할 수 없습니다: 🎜
  1. 🎜색인을 사용하여 직접 배열 항목을 설정하는 경우(예: vm.items[indexOfItem] = newValue🎜
  2. 🎜배열의 길이를 수정하는 경우, 예: vm.items.length = newLength🎜< /li>
🎜예: 🎜
<div>
  <span v-for="n in 10">{{ n }} </span>
</div>
🎜첫 번째 유형의 문제를 해결하기 위해 다음 두 가지 방법을 사용하면 vm.items[indexOfItem] = newValue와 동일한 효과를 얻을 수 있습니다. 반응형 시스템 내에서 트리거 상태 업데이트에도 사용됩니다. 🎜
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>
🎜vm.$set 전역 메서드 Vue.set의 별칭인 인스턴스 메서드: 🎜
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>
🎜두 번째 유형의 문제를 해결하려면 , splice:🎜
<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>
🎜🎜🎜

객체 변경 감지 고려 사항을 사용할 수 있습니다. Strong>
🎜또는 JavaScript 제한으로 인해 Vue는 객체 속성의 추가 또는 삭제를 감지할 수 없습니다: 🎜
<my-component v-for="item in items" :key="item.id"></my-component>
🎜이미 생성된 인스턴스의 경우 Vue는 감지하지 못합니다 루트 수준 반응형 속성을 동적으로 추가할 수 있습니다. 그러나 Vue.set(object, propertyName, value) 메서드를 사용하여 중첩된 객체에 반응형 속성을 추가할 수 있습니다. 예를 들면 다음과 같습니다. 🎜
<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>
🎜 중첩된 userProfile 개체에 새 age 속성을 ​​추가할 수 있습니다. 🎜
<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    >
    <button>Add</button>
  </form>
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>
🎜 vm.$set <을 사용할 수도 있습니다. /code> 인스턴스 메서드는 전역 Vue.set의 별칭일 뿐입니다. 🎜
Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">Remove</button>\
    </li>\
  ',
  props: ['title']
})
new Vue({
  el: '#todo-list-example',
  data: {
    newTodoText: '',
    todos: [
      {
        id: 1,
        title: 'Do the dishes',
      },
      {
        id: 2,
        title: 'Take out the trash',
      },
      {
        id: 3,
        title: 'Mow the lawn'
      }
    ],
    nextTodoId: 4
  },
  methods: {
    addNewTodo: function () {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})
🎜때로는 Object를 사용하는 것과 같이 기존 객체에 여러 개의 새 속성을 할당해야 할 수도 있습니다. 할당() 또는 _.extend(). 이 경우 두 개체의 속성을 모두 사용하여 새 개체를 만들어야 합니다. 따라서 새로운 반응형 속성을 추가하려면 다음과 같이 하는 대신 🎜rrreee🎜 다음과 같이 해야 합니다. 🎜rrreee🎜🎜🎜

필터링/정렬된 결과 표시


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

예:

rrreeerrreee

계산된 속성을 적용할 수 없는 경우(예: 중첩된 v-for 루프)에는 다음 메서드를 사용할 수 있습니다. v-for 循环中) 你可以使用一个方法:

rrreeerrreee


v-for 里使用值范围


v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

rrreee

结果:

1.jpg


<template> 上使用 v-for


类似于 v-if,你也可以利用带有 v-for<template> 来循环渲染一段包含多个元素的内容。比如:

rrreee


v-for 与 v-if 一同使用


注意我们推荐在同一元素上使用 v-if 和 v-for。更多细节可查阅 风格指南

当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:

rrreee

上面的代码将只渲染未完成的 todo。

而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>)上。如:

rrreee


在组件上使用 v-for


这部分内容假定你已经了解组件相关知识。你也完全可以先跳过它,以后再回来查看。

在自定义组件上,你可以像在任何普通元素上一样使用 v-for

rrreee

2.2.0+ 的版本里,当在组件上使用 v-for 时,keyrrreeerrreee

🎜🎜v-for에서 값 범위 사용 🎜🎜🎜🎜🎜v-for에는 정수도 허용됩니다. 이 경우 해당 템플릿을 해당 횟수만큼 반복합니다. 🎜rrreee🎜결과: 🎜🎜1.jpg🎜🎜
🎜

🎜🎜<template>에서 v-for 사용 🎜🎜🎜🎜🎜 <와 유사 code>v-if인 경우 v-for와 함께 <template>를 사용하여 루프에 여러 요소가 포함된 콘텐츠를 렌더링할 수도 있습니다. 예: 🎜rrreee🎜
🎜

🎜🎜v-for는 v-if🎜🎜🎜🎜
🎜와 함께 사용되므로 🎜 사용하지 마세요 🎜 동일한 요소를 사용하는 것이 좋습니다. v-ifv-for를 사용하세요. 자세한 내용은스타일 가이드. 🎜
🎜같은 노드에 있을 때 v-forv-if보다 우선순위가 높습니다. 이는 v-if를 의미합니다. code> code>는 각 v-for 루프에서 개별적으로 반복적으로 실행됩니다. 이 우선순위 메커니즘은 다음과 같이 일부 항목에 대한 노드만 렌더링하려는 경우에 유용합니다. 🎜rrreee🎜위 코드는 완료되지 않은 할일만 렌더링합니다. 🎜🎜그리고 루프 실행을 조건부로 건너뛰는 것이 목적이라면 v-if를 외부 요소(또는 <템플릿>). 예: 🎜rrreee🎜
🎜

🎜🎜구성 요소에 v-for 사용🎜🎜🎜🎜
🎜🎜이 부분에서는 여러분이 이미 이해하고 있다고 가정합니다. 🎜🎜Components🎜🎜관련 지식. 건너뛰고 나중에 다시 돌아올 수도 있습니다. 🎜🎜
🎜맞춤 구성요소에서는 일반 요소에서와 마찬가지로 v-for를 사용할 수 있습니다. 🎜rrreee
🎜🎜버전 2.2.0+에서는 구성 요소에서 v-for를 사용할 때 이제 key가 필요합니다. 🎜🎜

그러나 구성 요소에는 자체 독립 범위가 있으므로 데이터가 구성 요소에 자동으로 전달되지 않습니다. 반복 데이터를 컴포넌트에 전달하려면 prop:

rrreee

을 사용해야 합니다. item이 자동으로 컴포넌트에 삽입되지 않는 이유는 이렇게 하면 컴포넌트가 와 상호 작용하게 되기 때문입니다. v-for의 작업은 밀접하게 결합되어 있습니다. 구성 요소 데이터의 소스를 명확히 하면 해당 구성 요소를 다른 상황에서 재사용할 수 있습니다. item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

下面是一个简单的 todo 列表的完整例子:

rrreee

注意这里的 is="todo-item" 属性。这种做法在使用 DOM 模板时是十分必要的,因为在 <ul> 元素内只有 <li> 元素会被看作有效内容。这样做实现的效果与 <todo-item>다음은 간단한 할 일 목록의 전체 예입니다. rrreee

여기서 is="todo-item" 속성을 ​​참고하세요. 이 접근 방식은 DOM 템플릿을 사용할 때 매우 필요합니다.
    요소 내의
  • 요소만 유효한 콘텐츠로 간주되기 때문입니다. 이는 <todo-item>과 동일한 효과를 얻지만 잠재적인 브라우저 구문 분석 오류를 방지할 수 있습니다. 자세한 내용은
DOM 템플릿 구문 분석 지침

을 확인하세요. 1.gif

rrreee


🎜🎜 🎜