上一節,我們學習了在Vue中如何通過
v-if
和
v-show
根據條件渲染所需要的DOM元素或者模闆。在實際的項目中,我們很多時候會碰到将JSON資料中的數組或對象渲染出清單之類的元素。在Vue中,提供了一個
v-for
的指令,可以渲染清單。
v-for
的作用
v-for
v-for
可以基于源資料多次渲染元素或模闆塊。這個指令必須用特定的文法
alias in expression
,為目前周遊的元素提供别名:
<div v-for="alias in expression"> {{ alias }}</div>
一般都是給數組或對象指定别名,除此之外還可以為索引值指定别名,對于對象還可以給
value
指定别名,常見的幾種情形如下:
1 <div v-for="item in items">{{ item }}</div>
2 <div v-for="(item, index) in items">{{ item }} {{ index }}</div>
3 <div v-for="val in object"></div>
4 <div v-for="(val, key) in object"></div>
5 <div v-for="(val, key, index) in object"></div>
其中我們也可以把
in
換成
of
作為分隔符,因為它是最接近JavaScript疊代器的文法。
v-for
的預設行為試着不改變整體,而是替換元素。迫使其重新排序的元素,你需要提供一個
key
的特殊屬性:
接下來,我們看看
v-for
的一些使用場景。
一個數組的 v-for
v-for
使用
v-for
指令把數組的選項清單進行渲染。
v-for
指令需要使用
item in items
形式的特殊文法,
items
是源資料數組,
item
是數組元素疊代的别名。來看一個簡單的示例:
1 <!-- Template -->
2 <ul>
3 <li v-for="item in items">{{ item }}</li>
4 </ul>
5
6 // JavaScript
7 var app = new Vue({
8 el: '#app',
9 data: {
10 items: [1, 34, 89, 92, 45, 76, 33]
11 }
12 })
這個時候,數組
items
的每個
item
渲染到對應的
li
中,在浏覽器看到的效果如下:
上面的例子是通過
v-for
把數組
items
的每個項疊代出來放到
li
中,除此之外,還可以把數組的每個
index
也周遊出來。在上面的代碼的基礎上,咱們修改一下模闆:
1 <ul>
2 <li v-for="(item, index) in items">index-{{ index }}: {{ item }}</li>
3 </ul>
這個時候數組的索引号也周遊出來了:
從上面的示列看出來了,你需要哪個元素(HTML的标簽)循環,那麼
v-for
就寫在那個元素上。
上面我們已經可以正常的使用
v-for
将定義的數組每一項輸出來。為了加深學習,咱們在上面的示例基礎上增加一項需求,就是對輸出的數組進行排序。這個時候,咱們需要使用到Vue中的
computed
屬性。那麼
computed
屬性是做什麼的,我也不清楚,咱們一起先不去了解他吧,記作Vue有這麼一個屬性。随着後面的學習,我們會明白
computed
的用處的。
在Vue中,我們不能污染源資料,如果我們直接對源資料
items
通過
sort()
方法進行排序,将會報錯的:
1 var app = new Vue({
2 el: '#app',
3 computed: {
4 items: function() {
5 return this.items.sort()
6 }
7 },
8 data: {
9 items: [1, 34, 89, 92, 45, 76, 33]
10 }
11 })
為了不會污染Vue中的源資料,需要在
computed
裡重新聲明一個對象,比如聲明一個
sortItems
對象:
var app = new Vue({
el: '#app',
computed: {
sortItems: function() { return this.items.sort() } }, data: { items: [1, 34, 89, 92, 45, 76, 3, 12] } })
這個時候,我們的模闆也需要做對應的修改:
1 <ul>
2 <li v-for="item in sortItems">{{ item }}</li>
3 </ul>
如果不出意外的話,你看到的效果将是這樣的:
雖然有變化了,但不是我們想要的排序結果。雖然結果不是我們想要的,但這并不是Vue自身的問題,在JavaScript中也是這樣。如果我們要想真正的實作一個排序效果,那麼需要添加一個JavaScript的數組的排序函數的功能:
function sortNumber(a, b) {
return a - b
}
把
computed
裡的代碼也做一個相應的修改:
computed: {
sortItems: function() {
return this.items.sort(sortNumber)
}
}
這相輸出的效果才真正的是一個正确的排序效果:
有關于JavaScript中排序更多的介紹可以閱讀下面的文章:
- 數組的
和sort()
方法reverse()
- 排序算法
- JS中可能用得到的全部的排序算法
- JavaScript實作資料結構中的排序算法
- 排序圖解:JS排序算法實作
上面的例子,我們看到的是是一個簡單的純數字之類的數組,其其數組中的每個項也可以是對象,比如:
data: {
objItems: [
{
firstName: 'Jack',
lastName: 'Li',
age: 34
},
{
firstName: 'Airen',
lastName: 'Liao',
age: 18
}
]
}
我們把模闆換成:
1 <li v-for="objItem in objItems">{{ objItem.firstName }} {{objItem.lastName}} is {{ objItem.age}} years old!</li>
這個時候看到的效果如下:
在JavaScript中,我們有很多數組的方法,可以對數組進行操作,這些方法可以修改一個數組。其實,在Vue中同樣包含一組觀察數組變異方法,這些方法将會觸發元素的重新更新(視圖更新),這些方法也是JavaScript中數組中常看到的方法:
push()
、
pop()
、
shift()
、
unshift()
、
splice()
、
sort()
、
reverse()
。我們可以在控制台中簡單的看一下前面的示例中
items
數組調用變異方法的效果:
Vue不但提供了數組變異的方法,還提供了替換數組的方法。變異方法可以通過些方法的調用修改源資料中的數組;除此之外也有對應的非變異方法,比如
filter()
、
concat()
和
slice()
等。這些方法是不會改變源資料中的原始數組,但總是傳回一個新數組。當使用這些方法時,可以用新數組替換舊數組。
由于JavaScript的限制,Vue不能檢測以下變動的數組:
- 當你利用索引直接設定一個項時,例如
app.items[indexOfItem] = newValue
- 當你修改數組的長度時,例如:
app.items.length = newLength
為了解決第一類問題,以下兩種方式都可以實作和
app.items[indexOfItem = newValue
相同的效果,同時也将觸發狀态更新:
1 Vue.set(app.items, indexOfItem, newValue)
2
3 app.items.splice(indexOfItem, 1, newValue)
為了解決第二類問題,你可以使用
splice()
:
app.items.splice(newLength)
有關于JavaScript中數組相關的内容可以點選這裡或這裡。
對象的 v-for
v-for
v-for
除了可以使用在數組上之外還可以應用在對象上。
1 <!-- Template -->
2 <ul>
3 <li v-for="value in obj">{{ value }}</li>
4 </ul>
5
6 // JavaScript
7 obj: {
8 firstName: 'Airen',
9 lastName: 'Liao',
10 age: 30
11 }
使用
v-for
可以把
obj
的每個
key
對應的
value
值周遊出來,并且填到對應的
li
元素中。效果如下:
你也可以給對象的
key
周遊出來:
<ul>
<li v-for="(value, key) in obj">{{ key }}: {{ value }}</li>
</ul>
效果如下:
同樣,也可以類似數組一樣,可以把
index
索引做為第三個參數:
<ul>
<li v-for="(value, key, index) in obj">{{ index }}. {{ key }}: {{ value }}</li>
</ul>
前面提到過,數組可以變異,但對于對象而言,Vue不能檢測對象屬性的添加或删除。這主要也是由于JavaScript的限制。不過在Vue中,對于已經建立好的執行個體,可以使用
Vue.set(object, key, value)
方法向嵌套對象添加響應式屬性。例如:
var app = new Vue({
data: {
obj: {
name: 'Airen'
}
}
})
可以使用類似下面的方式,給
obj
對象添加一個新的屬性
age
:
回到我們的示例中給資料源中的
obj
添加一個
'from'
的
key
,而且其對應的
value
值為
'江西'
:
除了
Vue.set()
之外,還可以使用
app.$set
執行個體方法,它其實就是
Vue.set
的别名:
mounted(){
this.$set(this.obj, '職位', '碼農') }
這裡用到了Vue中的,和
mounted()
一樣,也不知道他在Vue中的作用,同樣放到後面來。我們總是會搞明白的。
computed
有時候你可能需要為已有對象賦予多個新屬性,比如使用
Object.assign()
或
_.extend()
。在這種情況下,應該用兩個對象的屬性建立一個新的對象。是以,如果你想添加新的響應式屬性,不要像這樣:
Object.assign(this.obj, {
age: 27,
favoriteColor: 'Vue Green'
})
應該這樣做:
this.obj = Object.assign({}, this.obj, {
age: 27,
favoriteColor: 'Vue Green'
})
一段取值範圍的 v-for
v-for
v-for
也可以取整數。在這種情況下,它将重複多次模闆:
<ul>
<li v-for="n in 10">{{ n }}</li> </ul>
結果如下:
v-for
和 一個 <template>
v-for
<template>
類似于
v-if
,你也可以利用帶有
v-for
的
<template>
渲染多個元素,比如:
<ul>
<template v-for="(value, key) in obj"> <li> <label :for="key">{{ key }}:</label> <input type="text" :placeholder="value" :id="key" /> </li> </template> </ul>
效果如下:
注意了,
v-for
和
<template>
一起使用的時候,需要把
v-for
寫在
<template>
元素上。另外上面的示例中,咱們還使用了Vue的一些其他特性,但這些特性不是這節内容所要學習的。後面我們會有機會一一介紹的。
一個元件的 v-for
v-for
在自定義元件裡,也可以像任何普通元素一樣用
v-for
。
<my-component v-for="item in items" :key="item.id"></my-component>
2.2.0+ 的版本裡,當在元件中使用時,
v-for
現在是必須的。
key
然而他不能自動傳遞資料到元件裡,因為元件有自己獨立的作用域。為了傳遞疊代資料到元件裡,我們要用
props
:
1 <my-component
2 v-for="(item, index) in items"
3 v-bind:item="item"
4 v-bind:index="index"
5 v-bind:key="item.id"
6 ></my-component>
不自動注入
item
到元件裡的原因是,因為這使得元件會與
v-for
的運作緊密耦合。在一些情況下,明确資料的來源可以使元件可重用。
來看一個簡單的Todo示例:
1 <div id="todo">
2 <input
3 v-model="newTodoText"
4 v-on:keyup.enter="addNewTodo"
5 placeholder="Add a todo"
6 />
7
8 <ul>
9 <li
10 is="todoItem"
11 v-for="(todo, index) in todos"
12 v-bind:title="todo"
13 v-on:remove="todos.splice(index, 1)"></li>
14 </ul>
15 </div>
16
17 Vue.component('todoItem', {
18 template:`
19 <li>
20 {{ title }}
21 <button v-on:click="$emit('remove')">x</button>
22 </li>
23 `,
24 props: ['title']
25 })
26
27 new Vue({
28 el: '#todo',
29 data: {
30 newTodoText: '',
31 todos: [
32 'Do the dishes',
33 'Take out the trash',
34 'Mow the lawn'
35 ]
36 },
37 methods: {
38 addNewTodo: function() {
39 this.todos.push(this.newTodoText)
40 this.newTodoText = ''
41 }
42 }
43 })
View Code
如果你和我一樣,對裡示例不能了解透徹,不用擔心,飯需要一口一口吃。如果你想急着了解清楚的話,可以閱讀下面的文章:
- 使用Vue.js 2建立To-Do App
- 使用Vue.js和Vuex 2.0建構一個簡單的Todo應用程式
總結
這篇文章主要總結了Vue的
v-for
指令。通過這個指令,配合資料源中的數組或者對象,我們可以很友善的生成清單。這也常常稱為清單渲染。當然配合一些模闆,我們可以做出一些特有的功能和效果。比如文章中最後一個Todo 清單,使用
v-for
很易實作。
著作權歸作者所有。
商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
原文: https://www.w3cplus.com/vue/v-for.html © w3cplus.com
轉載于:https://www.cnblogs.com/hlsy20180129/p/9277654.html