Vue v-for 组件
组件可以与 v-for 一起重用,以生成许多相同类型的元素。
当从组件中使用 v-for 生成元素时,可以根据数组中的值动态赋值 Props 也非常有用。
使用 v-for 创建组件元素
现在,我们将基于一个带有食物项目名称的数组,使用 v-for 创建组件元素。
实例
App.vue:
<template><h1>Food</h1><p>Components created with v-for based on an array.</p><div id="wrapper"><food-itemv-for="x in foods"v-bind:food-name="x"></food></div></template><script>export default {data() {return {foods: ['Apples','Pizza','Rice','Fish','Cake']};}}</script>
FoodItem.vue:
<template><div><h2>{{ foodName }}</h2></div></template><script>export default {props: ['foodName']}</script>
v-bind 简写
为了动态绑定 props,我们使用了 v-bind,因为我们现在将比以前更多地使用 v-bind,因此我们将在本教程的其余部分中使用 v-bind: 简写 :。
'key' 属性
如果我们在使用 v-for 创建元素后修改数组,则可能会出现错误,因为 Vue 更新使用 v-for 生成的元素的方式。Vue 重用元素来优化性能,因此,如果我们删除一个项,就会重用现有的元素,而不是重新创建所有元素,并且元素属性可能不再正确。
元素被错误地重用的原因是元素没有唯一的标识符,这正是我们使用 key 属性的目的:让 Vue 区分元素。我们将在没有 key 属性的情况下生成错误行为,但首先让我们使用 v-for 构建一个包含食物的网页来显示:食物名称、描述、喜爱食物的图像和更改喜爱状态的按钮。
实例
App.vue:
<template><h1>Food</h1><p>Food items are generated with v-for from the 'foods' array.</p><div id="wrapper"><food-itemv-for="x in foods":food-name="x.name":food-desc="x.desc":is-favorite="x.favorite"></food></div></template><script>export default {data() {return {foods: [{ name: 'Apples',desc: 'Apples are a type of fruit that grow on trees.',favorite: true },{ name: 'Pizza',desc: 'Pizza has a bread base with tomato sauce, cheese, and toppings on top.',favorite: false },{ name: 'Rice',desc: 'Rice is a type of grain that people like to eat.',favorite: false }{ name: 'Fish',desc: 'Fish is an animal that lives in water.',favorite: true }{ name: 'Cake',desc: 'Cake is something sweet that tastes good.',favorite: false }]};}}</script><style>#wrapper {display: flex;flex-wrap: wrap;}#wrapper > div {border: dashed black 1px;flex-basis: 120px;margin: 10px;padding: 10px;background-color: lightgreen;}</style>
FoodItem.vue:
<template><div><h2>{{ foodName }}<img src="/img_quality.svg" v-show="foodIsFavorite"></h2><p>{{ foodDesc }}</p><button v-on:click="toggleFavorite">Favorite</button></div></template><script>export default {props: ['foodName','foodDesc','isFavorite'],data() {return {foodIsFavorite: this.isFavorite}},methods: {toggleFavorite() {this.foodIsFavorite = !this.foodIsFavorite;}}}</script><style>img {height: 1.5em;float: right;}</style>
为了了解我们需要 key 属性,让我们创建一个按钮来删除数组中的第二个元素。当这种情况发生时,如果没有 key 属性,最喜欢的图像将从 'Fish' 元素转移到 'Cake' 元素,这是不正确的:
实例
与上一个实例的唯一区别是我们添加了一个按钮:
<button @click="removeItem">Remove Item</button>
还有一个在 App.vue 方法:
methods: {removeItem() {this.foods.splice(1,1);}}
如前所述:这个错误是,当元素被删除时,最喜欢的图像从 'fish' 到 'cake',这与 Vue 通过重用元素来优化页面有关,同时 Vue 无法完全区分元素。这就是为什么在使用 v-for 生成元素时,我们应该始终包含 key 属性以唯一地标记每个元素。当我们使用 key 属性时,我们不再遇到这个问题。
我们不使用数组元素索引作为 key 属性值,因为当删除和添加数组元素时,索引会发生变化。我们可以创建一个新的数据属性,为每种食物保留一个唯一的值,比如 ID 号,但由于食物已经有了唯一的名称,我们只能使用它:
实例
我们只需要在 App.vue 中添加一行,就可以唯一地识别使用 v-for 创建的每个元素,并解决问题:
<food-itemv-for="x in foods":key="x.name":food-name="x.name":food-desc="x.desc":is-favorite="x.favorite"/>