vue條件渲染和列表渲染

條件渲染

v-if

<h1 v-if="ok">Yes</h1>

<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
在<template>元素上使用v-if條件渲染分組

最終的渲染結(jié)果將不包含<template>元素贸典。

<template v-if="ok">
  <h1>Title</h1>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</template>
v-else
<div v-if="Math.random() > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div>

v-else元素必須緊跟在帶v-if或者v-else-if的元素的后面箕憾,否則它將不會被識別渤早。

v-else-if

2.1.0 新增

<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>

v-else-if也必須緊跟在帶v-if或者v-else-if的元素之后经柴。

用key管理可復(fù)用的元素

Vue會盡可能高效地渲染元素扇苞,通常會復(fù)用已有元素而不是從頭開始渲染录择。這么做除了使Vue變得非常快之外立美,還有其它一些好處匿又。例如,如果你允許用戶在不同的登錄方式之間切換:

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address">
</template>

那么在上面的代碼中切換loginType將不會清除用戶已經(jīng)輸入的內(nèi)容建蹄。因?yàn)閮蓚€(gè)模板使用了相同的元素碌更,<input>不會被替換掉——僅僅是替換了它的placeholder
這樣也不總是符合實(shí)際需求洞慎,所以Vue為你提供了一種方式來表達(dá)“這兩個(gè)元素是完全獨(dú)立的痛单,不要復(fù)用它們”。只需添加一個(gè)具有唯一值的key屬性即可劲腿。

<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="Enter your email address" key="email-input">
</template>

現(xiàn)在旭绒,每次切換時(shí),輸入框都將被重新渲染焦人。
注意挥吵,<label>元素仍然會被高效地復(fù)用,因?yàn)樗鼈儧]有添加key屬性花椭。

v-show

<h1 v-show="ok">Hello!</h1>

帶有v-show的元素始終會被渲染并保留在DOM中忽匈。v-show只是簡單地切換元素的CSS屬性display
注意矿辽,v-show不支持<template>元素丹允,也不支持v-else

v-if vs v-show

v-if是“真正”的條件渲染袋倔,因?yàn)樗鼤_保在切換過程中條件塊內(nèi)的事件監(jiān)聽器和子組件適當(dāng)?shù)乇讳N毀和重建雕蔽。
v-if也是惰性的:如果在初始渲染時(shí)條件為假,則什么也不做——直到條件第一次變?yōu)檎鏁r(shí)奕污,才會開始渲染條件塊萎羔。
相比之下,v-show就簡單得多——不管初始條件是什么碳默,元素總是會被渲染贾陷,并且只是簡單地基于CSS進(jìn)行切換缘眶。
一般來說,v-if有更高的切換開銷髓废,而v-show有更高的初始渲染開銷巷懈。因此,如果需要非常頻繁地切換慌洪,則使用v-show較好顶燕;如果在運(yùn)行時(shí)條件很少改變,則使用v-if較好冈爹。

v-if與v-for一起使用

當(dāng)v-ifv-for一起使用時(shí)涌攻,v-for具有比v-if更高的優(yōu)先級。

列表渲染

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

我們用v-for指令根據(jù)一組數(shù)組的選項(xiàng)列表進(jìn)行渲染频伤。v-for指令需要使用item in items形式的特殊語法恳谎,items是源數(shù)據(jù)數(shù)組并且item是數(shù)組元素迭代的別名。

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

v-for塊中憋肖,我們擁有對父作用域?qū)傩缘耐耆L問權(quán)限因痛。v-for還支持一個(gè)可選的第二個(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作為分隔符岸更,因?yàn)樗亲罱咏麶avaScript迭代器的語法鸵膏。

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

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

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

也可以提供第二個(gè)的參數(shù)為鍵名。

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

第三個(gè)參數(shù)為索引怎炊。

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

在遍歷對象時(shí)谭企,是按Object.keys()的結(jié)果遍歷,但是不能保證它的結(jié)果在不同的JavaScript引擎下是一致的结胀。

key

當(dāng)Vue.jsv-for正在更新已渲染過的元素列表時(shí)赞咙,它默認(rèn)用“就地復(fù)用”策略。如果數(shù)據(jù)項(xiàng)的順序被改變糟港,Vue將不會移動(dòng)DOM元素來匹配數(shù)據(jù)項(xiàng)的順序, 而是簡單復(fù)用此處每個(gè)元素院仿,并且確保它在特定索引下顯示已被渲染過的每個(gè)元素秸抚。這個(gè)類似Vue 1.xtrack-by="$index"
這個(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.xtrack-by鹿驼,但它的工作方式類似于一個(gè)屬性欲低,所以需要用v-bind來綁定動(dòng)態(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)樗?code>Vue識別節(jié)點(diǎn)的一個(gè)通用機(jī)制凄鼻,key并不與v-for特別關(guān)聯(lián)腊瑟,key還具有其他用途。

數(shù)組更新檢測

變異方法

Vue包含一組觀察數(shù)組的變異方法块蚌,所以它們也將會觸發(fā)視圖更新闰非。
這些方法有:push()pop()峭范、shift()财松、unshift()splice()虎敦、sort()游岳、reverse()

替換數(shù)組

變異方法其徙,顧名思義胚迫,會改變被這些方法調(diào)用的原始數(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)

由于JavaScript的限制,Vue不能檢測以下變動(dòng)的數(shù)組:

  1. 當(dāng)你利用索引直接設(shè)置一個(gè)項(xiàng)時(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)性的

為了解決第一類問題,以下兩種方式都可以實(shí)現(xiàn)和vm.items[indexOfItem] = newValue相同的效果,同時(shí)也將觸發(fā)狀態(tài)更新蒲赂。

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

你也可以使用vm.$set實(shí)例方法阱冶,該方法是全局方法 Vue.set 的一個(gè)別名:

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

為了解決第二類問題,可以使用splice凳宙。

vm.items.splice(newLength)</pre>

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

由于JavaScript的限制熙揍,Vue不能檢測對象屬性的添加或刪除。

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

對于已經(jīng)創(chuàng)建的實(shí)例氏涩,Vue不能動(dòng)態(tài)添加根級別的響應(yīng)式屬性届囚。但是,可以使用Vue.set(object, key, value)方法向嵌套對象添加響應(yīng)式屬性是尖。

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

你可以添加一個(gè)新的age屬性到嵌套的userProfile對象意系。

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

還可以使用vm.$set實(shí)例方法,它只是全局Vue.set的別名饺汹。

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

有時(shí)你可能需要為已有對象賦予多個(gè)新屬性蛔添,比如使用Object.assign()_.extend()。在這種情況下兜辞,應(yīng)該用兩個(gè)對象的屬性創(chuàng)建一個(gè)新的對象迎瞧。所以,如果你想添加新的響應(yīng)式屬性逸吵,不要像這樣:

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

應(yīng)該這樣做:

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

在計(jì)算屬性不適用的情況下 (例如韩脑,在嵌套v-for循環(huán)中) 你可以使用一個(gè)method方法氢妈。

<li v-for="n in even(numbers)">{{ n }}</li>
data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
methods: {
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

一段取值范圍的v-for

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

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

v-for on a <template>

類似于v-if,你也可以利用帶有v-for<template>渲染多個(gè)元素进苍。

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

v-for with v-if

當(dāng)它們處于同一節(jié)點(diǎn)蕾总,v-for的優(yōu)先級比v-if更高,這意味著v-if將分別重復(fù)運(yùn)行于每個(gè)v-for循環(huán)中琅捏。當(dāng)你想為僅有的一些項(xiàng)渲染節(jié)點(diǎn)時(shí),這種優(yōu)先級的機(jī)制會十分有用递雀。

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

上面的代碼只傳遞了未完成的todos柄延。
而如果你的目的是有條件地跳過循環(huán)的執(zhí)行,那么可以將v-if置于外層元素 或<template>上。

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

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

在自定義組件里搜吧,可以像任何普通元素一樣用v-for市俊。

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

2.2.0+的版本里,當(dāng)在組件中使用v-for時(shí)滤奈,key現(xiàn)在是必須的摆昧。
然而,任何數(shù)據(jù)都不會被自動(dòng)傳遞到組件里蜒程,因?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>

不自動(dòng)將item注入到組件里的原因是忌锯,這會使得組件與v-for的運(yùn)作緊密耦合。明確組件數(shù)據(jù)的來源能夠使組件在其他場合重復(fù)使用领炫。
下面是一個(gè)簡單的todo list的完整例子偶垮。

<div id="todo-list-example">
  <input
    v-model="newTodoText"
    v-on:keyup.enter="addNewTodo"
    placeholder="Add a todo"
  >
  <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)樵?code><ul>元素內(nèi)只有<li>元素會被看作有效內(nèi)容似舵。這樣做實(shí)現(xiàn)的效果與<todo-item>相同,但是可以避開一些潛在的瀏覽器解析錯(cuò)誤葱峡。

Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">X</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,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脆淹,死亡現(xiàn)場離奇詭異常空,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盖溺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門漓糙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人烘嘱,你說我怎么就攤上這事昆禽。” “怎么了蝇庭?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵醉鳖,是天一觀的道長。 經(jīng)常有香客問我哮内,道長盗棵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮纹因,結(jié)果婚禮上喷屋,老公的妹妹穿的比我還像新娘。我一直安慰自己瞭恰,他們只是感情好屯曹,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惊畏,像睡著了一般恶耽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上陕截,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天驳棱,我揣著相機(jī)與錄音,去河邊找鬼农曲。 笑死社搅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的乳规。 我是一名探鬼主播形葬,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼暮的!你這毒婦竟也來了笙以?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤冻辩,失蹤者是張志新(化名)和其女友劉穎猖腕,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恨闪,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倘感,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咙咽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片老玛。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖钧敞,靈堂內(nèi)的尸體忽然破棺而出蜡豹,到底是詐尸還是另有隱情,我是刑警寧澤溉苛,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布镜廉,位于F島的核電站,受9級特大地震影響愚战,放射性物質(zhì)發(fā)生泄漏桨吊。R本人自食惡果不足惜威根,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望视乐。 院中可真熱鬧,春花似錦敢茁、人聲如沸佑淀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伸刃。三九已至,卻和暖如春逢倍,著一層夾襖步出監(jiān)牢的瞬間捧颅,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工较雕, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留碉哑,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓亮蒋,卻偏偏與公主長得像扣典,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子慎玖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

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