Penyampaian senarai


directory


Gunakan v-for untuk memadankan tatasusunan dengan set elemen


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-forKami boleh menggunakan arahan v-for untuk memberikan senarai berdasarkan tatasusunan. Arahan v-for memerlukan sintaks khas dalam bentuk item dalam item, dengan item ialah tatasusunan data sumber dan item ialah

alias

elemen tatasusunan yang diulang.

<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>

Keputusan: 3.jpg

Dalam blok v-for, kami boleh mengakses semua sifat skop induk. v-for juga menyokong hujah kedua pilihan, indeks item semasa.

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>
4.jpgKeputusan:

🎜jpg🎜🎜Anda juga boleh menggunakan of dan bukannya in sebagai pembatas kerana ia lebih dekat dengan sintaks lelaran JavaScript: 🎜
<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>
🎜🎜🎜

🎜🎜Gunakan objek dalam v-for🎜


🎜Anda juga boleh menggunakan v-for untuk melintasi Sifat sesuatu objek. 🎜
<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>
example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})
🎜Hasil: 🎜🎜🎜🎜🎜Anda juga boleh memberikan parameter kedua sebagai nama hartanah (iaitu nama kunci): 🎜
var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
🎜🎜🎜

Anda juga boleh menggunakan parameter ketiga sebagai indeks:

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

5.jpg

Apabila melintasi objek, ia akan dilalui mengikut hasil Object.keys(), tetapi 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' }) tidak boleh

menjamin bahawa hasilnya adalah dalam Ia adalah konsisten di bawah enjin JavaScript yang berbeza.


Keadaan penyelenggaraan


Gunakan semasa Vue sedang dikemas kini Apabila v-for memaparkan senarai elemen, ia menggunakan strategi "kemas kini di tempat" secara lalai. Jika susunan item data diubah, Vue tidak akan mengalihkan elemen DOM untuk memadankan susunan item data, tetapi akan mengemas kini setiap elemen di tempatnya dan memastikan ia dipaparkan dengan betul pada setiap kedudukan indeks. Ini serupa dengan track-by="$index" Vue 1.x.

🎜Mod lalai ini cekap, tetapi 🎜hanya digunakan pada output pemaparan senarai🎜 yang tidak bergantung pada keadaan subkomponen atau keadaan DOM sementara (cth. nilai input borang). 🎜🎜Untuk memberi Vue petunjuk supaya ia dapat menjejaki identiti setiap nod dan dengan itu menggunakan semula dan menyusun semula elemen sedia ada, anda perlu menyediakan atribut key unik untuk setiap item: 🎜
vm.items.splice(newLength)
🎜Disyorkan Anda boleh menyediakan atribut key apabila menggunakan v-for melainkan melintasi kandungan DOM output adalah sangat mudah, atau tingkah laku lalai sengaja diharap untuk memperoleh prestasi. 🎜🎜Oleh kerana ia adalah mekanisme umum untuk Vue mengenal pasti nod, key tidak berkaitan secara khusus hanya dengan v-for. Seperti yang akan kita lihat kemudian dalam panduan, ia juga mempunyai kegunaan lain. 🎜🎜🎜Jangan gunakan nilai jenis bukan asas seperti objek atau tatasusunan sebagai key v-for. Sila gunakan rentetan atau nilai angka. 🎜🎜Untuk penggunaan lebih terperinci atribut key, sila pergi ke Dokumentasi API untuk key. 🎜🎜🎜🎜

🎜Array pengesanan kemas kini🎜🎜


🎜🎜🎜

🎜🎜kaedah mutasi🎜🎜🎜🎜Vue membungkus kaedah mutasi tatasusunan yang didengar, jadi kaedah ini juga akan mencetuskan kemas kini paparan. Kaedah yang dibalut ini termasuk: 🎜

  • 🎜push()🎜
  • 🎜 pop() 🎜
  • 🎜shift()🎜
  • 🎜nyahshift()🎜
  • 🎜splice()🎜
  • 🎜isih()🎜
  • 🎜terbalik()🎜
🎜Anda boleh membuka konsol dan cuba memanggil kaedah mutasi pada tatasusunan item dalam contoh sebelumnya. Contohnya, example1.items.push({ message: 'Baz' }). 🎜🎜🎜🎜🎜🎜🎜Ganti array🎜🎜🎜

Kaedah mutasi, seperti namanya, akan menukar tatasusunan asal di mana kaedah ini dipanggil. Sebaliknya, terdapat juga kaedah tidak bermutasi, seperti filter(), concat() dan slice(). Mereka tidak mengubah tatasusunan asal, tetapi sentiasa mengembalikan tatasusunan baharu. Apabila menggunakan pendekatan tidak bermutasi, anda boleh menggantikan tatasusunan lama dengan yang baharu: 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
    })
  }
}

Anda mungkin berfikir bahawa ini akan menyebabkan Vue membuang DOM sedia ada dan memaparkan semula keseluruhan senarai. Nasib baik, ini tidak berlaku. Vue melaksanakan beberapa heuristik pintar untuk memaksimumkan penggunaan semula elemen DOM, jadi menggantikan tatasusunan asal dengan tatasusunan yang mengandungi elemen yang sama adalah operasi yang sangat cekap.


Nota

🎜Disebabkan pengehadan JavaScript, Vue < strong>Tidak boleh mengesan perubahan dalam tatasusunan berikut: 🎜
  1. 🎜Apabila anda menetapkan item tatasusunan secara terus menggunakan indeks, contohnya: vm.items[indexOfItem] = newValue🎜
  2. 🎜Apabila anda mengubah suai panjang tatasusunan, contohnya: vm.items.length = newLength🎜< /li>
🎜Contohnya: 🎜
<div>
  <span v-for="n in 10">{{ n }} </span>
</div>
🎜Untuk menyelesaikan jenis masalah pertama, dua kaedah berikut boleh mencapai kesan yang sama seperti vm.items[indexOfItem] = newValue, dan juga akan digunakan dalam kemas kini status Pencetus dalam sistem reaktif: 🎜
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>
🎜Anda juga boleh menggunakan vm. $set kaedah contoh, yang merupakan alias kaedah global Vue.set: 🎜
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>
🎜Untuk menyelesaikan jenis masalah kedua , anda boleh menggunakan splice< /code>:🎜
<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>
🎜🎜🎜

Pertimbangan pengesanan perubahan objek
🎜Atau disebabkan oleh pengehadan JavaScript, Vue tidak dapat mengesan penambahan atau pemadaman sifat objek: 🎜
<my-component v-for="item in items" :key="item.id"></my-component>
🎜Untuk contoh yang telah dibuat, Vue tidak benarkan menambahkan sifat responsif peringkat akar secara dinamik. Walau bagaimanapun, anda boleh menambah sifat reaktif pada objek bersarang menggunakan kaedah Vue.set(object, propertyName, value). Contohnya, untuk: 🎜
<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>
🎜 Anda boleh menambah sifat age baharu pada objek userProfile: 🎜
<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>
🎜Anda juga boleh menggunakan vm.$set < /code> Kaedah instance, ia hanyalah alias kepada Vue.set global: 🎜
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 = ''
    }
  }
})
🎜 Kadangkala anda mungkin perlu menetapkan berbilang sifat baharu pada objek sedia ada, seperti menggunakan Object. assign() atau _.extend(). Dalam kes ini, anda harus mencipta objek baharu dengan sifat kedua-dua objek. Jadi, jika anda ingin menambah atribut responsif baharu, bukannya seperti ini: 🎜rrreee🎜 anda harus melakukan ini: 🎜rrreee🎜🎜🎜

Tunjukkan hasil yang ditapis/diisih


Kadangkala kita ingin menunjukkan versi tatasusunan yang ditapis atau diisih tanpa mengubah atau menetapkan semula data asal. Dalam kes ini, anda boleh mencipta sifat terkira yang mengembalikan tatasusunan yang ditapis atau diisih.

Contohnya:

rrreeerrreee

Dalam kes di mana sifat yang dikira tidak berkenaan (contohnya, dalam gelung v-for bersarang) anda boleh menggunakan kaedah: 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

🎜🎜Gunakan julat nilai dalam v-for 🎜🎜🎜🎜🎜v-for juga boleh menerima integer. Dalam kes ini, ia akan mengulang templat bilangan kali yang sepadan. 🎜rrreee🎜Keputusan: 🎜🎜🎜🎜
🎜

🎜🎜Gunakan v-for pada <template> 🎜🎜🎜🎜🎜Serupa dengan < kod>v-jika, anda juga boleh menggunakan <template> dengan v-for untuk memaparkan kandungan yang mengandungi berbilang elemen dalam satu gelung. Contohnya: 🎜rrreee🎜
🎜

🎜🎜v-for digunakan bersama-sama dengan v-if🎜🎜🎜🎜
🎜Perhatikan bahawa kami 🎜 tidak 🎜 mengesyorkan menggunakan elemen yang sama Gunakan v-if dan v-for. Butiran lanjut boleh didapatigaya Panduan. 🎜
🎜Apabila mereka berada pada nod yang sama, v-for mempunyai keutamaan yang lebih tinggi daripada v-if, yang bermaksud v-if code> akan dijalankan secara individu dan berulang kali dalam setiap gelung v-for. Mekanisme keutamaan ini berguna apabila anda hanya mahu membuat nod untuk beberapa item, seperti berikut: 🎜rrreee🎜Kod di atas hanya akan memaparkan todos yang belum selesai. 🎜🎜Dan jika tujuan anda adalah untuk melangkau pelaksanaan gelung secara bersyarat, maka anda boleh meletakkan v-if dalam elemen luar (atau <template>). Seperti: 🎜rrreee🎜
🎜

🎜🎜Gunakan v-for pada komponen🎜🎜🎜🎜
🎜🎜Bahagian ini menganggap anda sudah fahami 🎜🎜Komponen🎜🎜Pengetahuan berkaitan. Anda juga boleh melangkaunya dan kembali kepadanya kemudian. 🎜🎜
🎜Pada komponen tersuai, anda boleh menggunakan v-for seperti yang anda lakukan pada mana-mana elemen biasa. 🎜rrreee
🎜🎜Dalam versi 2.2.0+, apabila menggunakan v-for pada komponen, key kini diperlukan. 🎜🎜

Walau bagaimanapun, tiada data akan dihantar secara automatik kepada komponen kerana komponen tersebut mempunyai skop bebasnya sendiri. Untuk menghantar data lelaran kepada komponen, kita perlu menggunakan prop:

rrreee

Sebab mengapa item tidak disuntik secara automatik ke dalam komponen ialah ini akan menjadikan komponen berbeza daripada operasi v-fordigandingkan dengan ketat. Menjelaskan sumber data komponen membolehkan komponen itu digunakan semula dalam situasi lain. item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

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

rrreee

注意这里的 is="todo-item" 属性。这种做法在使用 DOM 模板时是十分必要的,因为在 <ul> 元素内只有 <li> 元素会被看作有效内容。这样做实现的效果与 <todo-item>Berikut ialah contoh lengkap senarai tugasan mudah: rrreee

Perhatikan atribut is="todo-item" di sini. Pendekatan ini sangat diperlukan apabila menggunakan templat DOM, kerana hanya elemen <li> dalam elemen <ul> akan dianggap sebagai kandungan yang sah. Ini mencapai kesan yang sama seperti <todo-item>, tetapi boleh mengelakkan beberapa kemungkinan ralat penghuraian penyemak imbas. Lihat
Arahan Penghuraian Templat DOM

untuk mengetahui lebih lanjut. 1.gif

rrreee


🎜🎜 🎜