VUE復(fù)習(xí)筆記8(列表渲染)

用 v-for 把一個(gè)數(shù)組 對應(yīng)為 一組元素

我們使用 v-for 指令根據(jù)數(shù)組的列表來進(jìn)行渲染。
v-for指令需要使用 item,idx in items這樣特殊的語法窘游, items是源數(shù)據(jù)數(shù)組,item則是數(shù)組中的每一項(xiàng)榜田。idx代表索引填大,但是idx不是必須的。

<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' }
    ]
  }
})

列表輸入 foo bar兩項(xiàng)

v-for 塊中燕垃,我們擁有對父級作用域的完全訪問權(quán)枢劝,v-for還支持一個(gè)可選的第二參數(shù)作為當(dāng)前項(xiàng)的索引。

<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' }
    ]
  }
})

也可以使用 of 代替 in作為分隔符卜壕,如下:

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

一個(gè)對象的 v-for

我們也可以用 v-for 通過一個(gè)對象的屬性來迭代您旁,而不只是數(shù)組。

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

new Vue({
  el: '#v-for-object',
  data: {
    object: {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    }
  }
})

輸出 john doe 30
我們也可以提供使用第二個(gè)參數(shù)作為鍵名

<div v-for="(value, key) in object">
  {{ key }}: {{ value }}
</div>

輸出
firstName:john
lastName:doe
age:30

也就是說轴捎,在使用數(shù)組循環(huán)的時(shí)候鹤盒,參數(shù)分別為:item當(dāng)前項(xiàng)和第二參數(shù)索引index
在使用對象循環(huán)時(shí),參數(shù)分別為 當(dāng)前想item的value侦副,item的key和他的索引index

key

當(dāng) vuejs 使用 v-for 更新已經(jīng)渲染過的元素列表時(shí)侦锯,它默認(rèn)用“就地復(fù)用”策略。
如果數(shù)據(jù)項(xiàng)的順序改變秦驯,vue也不會移動dom來匹配數(shù)據(jù)項(xiàng)的順序尺碰,而只是簡單的復(fù)用每個(gè)元素,并且確保它在特定索引下顯示已被渲染過的每個(gè)元素译隘。

這個(gè)默認(rèn)的模式是高效的亲桥,但是只適用于不依賴子組件狀態(tài)或臨時(shí) DOM 狀態(tài) (例如:表單輸入值) 的列表渲染輸出。

為了給 Vue 一個(gè)提示固耘,以便它能跟蹤每個(gè)節(jié)點(diǎn)的身份题篷,從而重用和重新排序現(xiàn)有元素,你需要為每項(xiàng)提供一個(gè)唯一 key 屬性厅目。理想的 key 值是每項(xiàng)都有的且唯一的 id番枚。這個(gè)特殊的屬性相當(dāng)于 Vue 1.x 的 track-by ,但它的工作方式類似于一個(gè)屬性损敷,所以你需要用 v-bind 來綁定動態(tài)值 (在這里使用簡寫):

<div v-for="item in items" :key="item.id">
  <!-- 內(nèi)容 -->
</div>

建議盡可能在使用 v-for 時(shí)提供 key葫笼,除非遍歷輸出的 DOM 內(nèi)容非常簡單,或者是刻意依賴默認(rèn)行為以獲取性能上的提升嗤锉。

因?yàn)樗?Vue 識別節(jié)點(diǎn)的一個(gè)通用機(jī)制渔欢,key 并不與 v-for 特別關(guān)聯(lián),key 還具有其他用途瘟忱,我們將在后面的指南中看到其他用途奥额。

數(shù)組更新檢測

變異方法

vue中還包含一些數(shù)組變異的方法苫幢,所以他們也會觸發(fā)視圖的更新。
Vue 包含一組觀察數(shù)組的變異方法垫挨,所以它們也將會觸發(fā)視圖更新韩肝。這些方法如下:

push() //數(shù)組最后插入添加一個(gè)
pop() //刪除數(shù)組的最后一個(gè)元素
shift() //刪除數(shù)組的第一個(gè)元素
unshift()  //數(shù)組開頭添加一個(gè)或多個(gè)元素
splice()  //法向/從數(shù)組中添加/刪除項(xiàng)目
sort() //數(shù)組排序
reverse() //顛倒數(shù)組中元素的排序

//demo
example1.items.push({ message: 'Baz' }) 。

替換數(shù)組

以上的變異方法九榔,顧名思義會改變原始的數(shù)組哀峻,相比之下,也有非變異的方法哲泊。例如:filter(), concat() 和 slice() 剩蟀。這些不會改變原始數(shù)組,但總是返回一個(gè)新數(shù)組切威。當(dāng)使用非變異方法時(shí)育特,可以用新數(shù)組替換舊數(shù)組:

example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})

你可能認(rèn)為這將導(dǎo)致 Vue 丟棄現(xiàn)有 DOM 并重新渲染整個(gè)列表。幸運(yùn)的是先朦,事實(shí)并非如此缰冤。Vue 為了使得 DOM 元素得到最大范圍的重用而實(shí)現(xiàn)了一些智能的、啟發(fā)式的方法喳魏,所以用一個(gè)含有相同元素的數(shù)組去替換原來的數(shù)組是非常高效的操作棉浸。

注意事項(xiàng)

由于 js 的限制,vue不能夠檢測到以下數(shù)組的變化
1.當(dāng)使用索引直接對一個(gè)項(xiàng)進(jìn)行設(shè)置時(shí)

vm.items[indexOfItem] = newValue

2.當(dāng)修改數(shù)組長度時(shí)

vm.items.length = newLength

舉例:

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是響應(yīng)性的
vm.items.length = 2 // 不是響應(yīng)性的

以上雖然可以修改刺彩,但是vue檢測不到迷郑,所以就不是響應(yīng)式的。
這里列舉了 解決第一類問題的2種方法:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
//分別是 數(shù)組迂苛、數(shù)組索引三热、新添加對應(yīng)索引的值

// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)鼓择;
//分別是 數(shù)組的索引位置三幻,添加個(gè)數(shù),添加的值

解決第二類問題的方法

vm.items.splice(newLength)

對象更改檢測注意事項(xiàng)

由于js 的限制呐能,vue不能檢測對象屬性的添加和刪除

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 現(xiàn)在是響應(yīng)式的

vm.b = 2
// `vm.b` 不是響應(yīng)式的念搬,因?yàn)檫@里的b是新添加的,無法檢測到摆出。

對于已經(jīng)創(chuàng)建的實(shí)例朗徊,vue不能夠動態(tài)添加根級別的響應(yīng)式屬性,但是偎漫,可以使用 Vue.set(object, key, value) 方法向嵌套對象添加響應(yīng)式屬性爷恳。例如,對于:

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

這時(shí)可以添加一個(gè)新的 age 屬性到嵌套的 userProfile 對象:

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

有時(shí)候可能需要對已有對象賦多個(gè)新屬性象踊,比如使用 Object.assign() 或 _.extend()温亲。在這種情況下棚壁,你應(yīng)該用兩個(gè)對象的屬性創(chuàng)建一個(gè)新的對象。

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

顯示過濾排序結(jié)果

有時(shí)候需要顯示一個(gè)數(shù)組的過濾或者排序的副本栈虚,而不實(shí)際改變或者重置原始數(shù)據(jù)袖外,這種情況下,可以創(chuàng)建返回過濾或者排序數(shù)組的計(jì)算屬性魂务。

<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
    })
  }
}
//這里返回能夠被2整除的 2和4

如果在計(jì)算屬性不適合的情況下則使用 methods

一段范圍內(nèi)的取值

v-for也可以取整數(shù)曼验。在這種情況下,它將重復(fù)多次模板粘姜。

//循環(huán)10次
<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

v-for on a <template>

類似 v-if鬓照,我們也可以利用帶有 v-fortemplate渲染多個(gè)元素

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

v-for with v-if

當(dāng)他們處于同一個(gè)節(jié)點(diǎn)時(shí),v-for的優(yōu)先級高于v-if孤紧,也就是說颖杏,先進(jìn)行循環(huán)再判斷。
比如下面這個(gè)列表坛芽,我們只想渲染部分節(jié)點(diǎn)留储,這時(shí)候v-if判斷就很有用。

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

上面的代碼只傳遞了未完成的 todos咙轩。

如果我們的目的是先進(jìn)行判斷获讳,在看是否有必要循環(huán),就可以將 v-if包裹在外層的div中活喊。

<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>

一個(gè)組件的 v-for

了解組件相關(guān)知識丐膝,查看 組件。完全可以先跳過它钾菊,以后再回來查看帅矗。

在自定義組件中,我們可以像普通元素那樣使用 v-for煞烫。

<my-component v-for="item in items" :key="item.id"></my-component>

注意:2.2.0的版本中浑此,v-for對應(yīng)的key也是必須填寫的。

然而任何數(shù)組都不會被自動傳遞到組件中滞详,因?yàn)榻M件有自己獨(dú)立的作用域凛俱,為了把迭代的數(shù)據(jù)傳遞到組件里,我們要使用props料饥。

<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>

不自動將 item 注入到組件里的原因是蒲犬,這會使得組件與 v-for 的運(yùn)作緊密耦合。明確組件數(shù)據(jù)的來源能夠使組件在其他場合重復(fù)使用岸啡。

下面是一個(gè)簡單的 todo list 的完整例子:

<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>

注意這里的 is="todo-item" 屬性原叮。這種做法在使用 DOM 模板時(shí)是十分必要的,因?yàn)樵?<ul> 元素內(nèi)只有 <li> 元素會被看作有效內(nèi)容。這樣做實(shí)現(xiàn)的效果與 <todo-item> 相同奋隶,但是可以避開一些潛在的瀏覽器解析錯誤沛慢。查看 DOM 模板解析說明 來了解更多信息。

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 = ''
    }
  }
})
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末达布,一起剝皮案震驚了整個(gè)濱河市团甲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌黍聂,老刑警劉巖躺苦,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異产还,居然都是意外死亡匹厘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門脐区,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愈诚,“玉大人,你說我怎么就攤上這事牛隅】蝗幔” “怎么了?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵媒佣,是天一觀的道長匕累。 經(jīng)常有香客問我,道長默伍,這世上最難降的妖魔是什么欢嘿? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮也糊,結(jié)果婚禮上炼蹦,老公的妹妹穿的比我還像新娘。我一直安慰自己狸剃,他們只是感情好掐隐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著捕捂,像睡著了一般瑟枫。 火紅的嫁衣襯著肌膚如雪斗搞。 梳的紋絲不亂的頭發(fā)上指攒,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天,我揣著相機(jī)與錄音僻焚,去河邊找鬼允悦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的隙弛。 我是一名探鬼主播架馋,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼全闷!你這毒婦竟也來了叉寂?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤总珠,失蹤者是張志新(化名)和其女友劉穎屏鳍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體局服,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钓瞭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了淫奔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片山涡。...
    茶點(diǎn)故事閱讀 38,683評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖唆迁,靈堂內(nèi)的尸體忽然破棺而出鸭丛,到底是詐尸還是另有隱情,我是刑警寧澤唐责,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布系吩,位于F島的核電站,受9級特大地震影響妒蔚,放射性物質(zhì)發(fā)生泄漏穿挨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一肴盏、第九天 我趴在偏房一處隱蔽的房頂上張望科盛。 院中可真熱鬧,春花似錦菜皂、人聲如沸贞绵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽榨崩。三九已至,卻和暖如春章母,著一層夾襖步出監(jiān)牢的瞬間母蛛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工乳怎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留彩郊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像秫逝,于是被迫代替她去往敵國和親恕出。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,046評論 0 29
  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨(dú)立版本劣摇,Vue即被注冊為全局變量,可以在頁面使用了狈醉。 如果希望搭建...
    Awey閱讀 11,002評論 4 129
  • vue概述 在官方文檔中,有一句話對Vue的定位說的很明確:Vue.js 的核心是一個(gè)允許采用簡潔的模板語法來聲明...
    li4065閱讀 7,193評論 0 25
  • 主要還是自己看的惠险,所有內(nèi)容來自官方文檔苗傅。 介紹 Vue.js 是什么 Vue (讀音 /vju?/,類似于 vie...
    Leonzai閱讀 3,334評論 0 25
  • 一 你覺得愛情中儀式感重要嗎班巩? 我之前一直覺得只要兩個(gè)人互相喜歡渣慕,有沒有儀式感并不重要。 但橙子卻不這么認(rèn)為抱慌,她覺...
    未末小七閱讀 1,487評論 3 13