上一篇介紹了Vue的模板內容,而對於通常的模板引擎來講,除了模板內容,還包括模板邏輯。經常使用的模板邏輯包括條件和循環。本文將詳細介紹Vue模板邏輯html
在Vue中,實現條件邏輯依靠條件指令,包括v-if、v-else、v-else-if這三個vue
【v-if】數組
根據表達式的值的真假條件渲染元素。賦值爲true時,將元素插入DOM中, 不然對應元素從DOM中移除app
所以,Vue裏的v-if指令相似於模板引擎的if條件語句性能
<div id="app" v-if="seen"> {{ message }} </div>
上面代碼中,若是"seen"的值爲true,則"#app"元素顯示,不然將從DOM中移除this
<script> var app = new Vue({ el: '#app', data: { message: 'Hello Vue!', seen:true } }) </script>
若是想切換多個元素,能夠把一個<template>
元素當作包裝元素,並在上面使用v-if
。最終的渲染結果不會包含<template>
元素spa
<div id="app"> <template v-if="ok"> <h1>Title</h1> <p>Paragraph 1</p> <p>Paragraph 2</p> </template> </div>
<script> var app = new Vue({ el: '#app', data:{ ok:true } }) </script>
【v-else-if】3d
表示 v-if
的 「else if 塊」。能夠鏈式調用。前一兄弟元素必須有 v-if
或 v-else-if
code
【v-else】component
爲 v-if
或者 v-else-if
添加 「else 塊」。 前一兄弟元素必須有 v-if
或 v-else-if
下面代碼中,當type='A'時,顯示內容爲A的div;當type='B'時,顯示內容爲B的div;當type='C'時,顯示內容爲C的div;不然,顯示內容爲D的div
<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>D</div>
<script> var app = new Vue({ el: "#app", data: { type:'A' } }) </script>
Vue會盡量高效地渲染元素,一般會複用已有元素而不是從頭開始渲染。這麼作,除了使 Vue 變得很是快以外,還有一些有用的好處
例如,若是容許用戶在不一樣的登陸方式之間切換
<div id="app"> <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="輸入用戶名"> </template> <template v-else> <label>Email</label> <input placeholder="輸入郵箱地址"> </template> <div> <button @click="toggle">切換登陸方式</button> </div> </div>
<script> var app = new Vue({ el: '#app', data:{ loginType:'username' }, methods:{ toggle(){ if(this.loginType === 'username'){ this.loginType = ''; }else{ this.loginType = 'username'; } } } }) </script>
【key屬性】
這樣也不老是符合實際需求,因此Vue提供了一種方式來聲明「這兩個元素是徹底獨立的——不要複用它們」。只需添加一個具備惟一值的key
屬性便可
<div id="app"> <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="輸入用戶名" key="username-input"> </template> <template v-else> <label>Email</label> <input placeholder="輸入郵箱地址" key="email-input"> </template> <div> <button @click="toggle">切換登陸方式</button> </div> </div>
<script> var app = new Vue({ el: '#app', data:{ loginType:'username' }, methods:{ toggle(){ if(this.loginType === 'username'){ this.loginType = ''; }else{ this.loginType = 'username'; } } } }) </script>
如今,每次切換時,輸入框都將被從新渲染
[注意]<label>
元素仍然會被高效地複用,由於它們沒有添加 key
屬性
【v-show】
根據表達式的真假值,切換元素的display
屬性。當v-show被賦值爲true時,元素顯示;不然,元素被隱藏
v-show和v-if指令都有元素顯隱的功能,但其原理並不相同。v-if的元素顯隱會將元素從DOM刪除或插入;而v-show則只是改變該元素的display是否爲none
[注意]v-show
不支持 <template>
語法,也不支持 v-else
v-if vs v-show
v-if
是「真正的」條件渲染,由於它確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。v-if
是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真,纔開始渲染條件塊
而v-show
就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於CSS進行切換
通常來講, v-if
有更高的切換開銷,而v-show
有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用v-show
較好;若是在運行時條件不太可能改變,則使用v-if
較好
<div id="app"> <div v-if="num > 0">if</div> <div v-show="num > 0">show</div> </div>
上面代碼中,若是num>0,則內容爲if和內容爲show的div都顯示;不然都不顯示
<script> var app = new Vue({ el: "#app", data: { num: 1 } }) </script>
上圖所示,當num=0時,內容爲if的div直接從DOM移除,而內容爲show的div的display爲none
【v-for】
v-for指令基於源數據屢次渲染元素或模板塊,包含如下用法
數組迭代
用 v-for
指令根據一組數組的選項列表進行渲染。 v-for
指令須要以 item in items
形式的特殊語法, items
是源數據數組而且 item
是數組元素迭代的別名
v-for="item in items"
<ul id="example-1"> <li v-for="item in items"> {{ item.message }} </li> </ul>
<script> var example1 = new Vue({ el: '#example-1', data: { items: [ {message: 'Foo' }, {message: 'Bar' } ] } }) </script>
在v-for
塊中,擁有對父做用域屬性的徹底訪問權限。v-for
還支持一個可選的第二個參數爲當前項的索引
v-for="(item, index) in items"
<ul id="example-2"> <li v-for="(item, index) in items"> {{ parentMessage }} - {{ index }} - {{ item.message }} </li> </ul>
<script> var example2 = new Vue({ el: '#example-2', data: { parentMessage: 'Parent', items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) </script>
也能夠用 of
替代 in
做爲分隔符,它是最接近JS迭代器的語法
<ul id="example-2"> <li v-for="(item, index) of items"> {{ parentMessage }} - {{ index }} - {{ item.message }} </li> </ul>
<script> var example2 = new Vue({ el: '#example-2', data: { parentMessage: 'Parent', items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) </script>
和v-if
模板同樣,也能夠用帶有v-for
的<template>
標籤來渲染多個元素塊
<ul id="example-2"> <template v-for="item in items"> <li>{{ item.message }}</li> <li>abc</li> </template> </ul>
<script> var example2 = new Vue({ el: '#example-2', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) </script>
對象迭代
能夠用 v-for
經過一個對象的屬性來迭代,第二個參數爲鍵名,第三個參數爲索引
v-for="(value, key, index) in object"
<ul id="repeat-object" class="demo"> <li v-for="(value, key, index) in object"> {{ index }}. {{ key }} : {{ value }} </li> </ul>
<script> new Vue({ el: '#repeat-object', data: { object: { firstName: 'John', lastName: 'Doe', age: 30 } } }) </script>
整數迭代
v-for
也能夠取整數。在這種狀況下,它將重複屢次模板
[注意]整數迭代是從1開始,而不是從0開始的
<div id="example"> <span v-for="n in 10">{{ n }} </span> </div>
<script> var example = new Vue({ el: '#example' }) </script>
【組件】
在自定義組件裏,能夠像任何普通元素同樣用v-for
<my-component v-for="item in items" :key="item.id"></my-component>
[注意]2.2.0+ 的版本里,當在組件中使用 v-for
時,key
如今是必須的
然而不能自動傳遞數據到組件裏,由於組件有本身獨立的做用域。爲了傳遞迭代數據到組件裏,要用 props
不自動注入 item
到組件裏的緣由是,由於這使得組件會緊密耦合到 v-for
如何運做。在一些狀況下,明確數據的來源可使組件可重用
<div id="example"> <my-component v-for="(item,index) in items" :msg="item.message" :index="index" :key="item.id"></my-component> </div>
<script> // 註冊 Vue.component('my-component', { template: '<div>{{index}}.{{msg}}</div>', props:['index','msg'] }) // 建立根實例 new Vue({ el: '#example', data(){ return { items: [ {id:1, message: 'Foo' }, {id:2, message: 'Bar' }, {id:3, message: 'Baz' }, ] } } }) </script>
【v-for with v-if】
當它們處於同一節點,v-for
的優先級比v-if
更高,這意味着v-if
將分別重複運行於每一個v-for
循環中。當想爲僅有的一些項渲染節點時,這種優先級的機制會十分有用
<ul id="example"> <li v-for="item in items" v-if="item.isShow"> {{ item.message }} </li> </ul>
<script> var example = new Vue({ el: '#example', data: { items: [ {isShow: true,message: 'Foo' }, {isShow: false,message: 'Bar' }, {isShow: true,message: 'Baz' } ] } }) </script>
若是要有條件地跳過循環的執行,那麼將 v-if
置於包裝元素 (或 <template>
)上
<ul id="example" v-if="isShow"> <li v-for="(item,index) in items" > {{ item.message }} </li> </ul>
<script> var example = new Vue({ el: '#example', data: { isShow:true, items: [ {message: 'Foo' }, {message: 'Bar' }, {message: 'Baz' } ] } }) </script>
【key】
當Vue.js用v-for
正在更新已渲染過的元素列表時,它默認用 「就地複用」 策略。若是數據項的順序被改變,Vue將不是移動DOM元素來匹配數據項的順序, 而是簡單複用此處每一個元素,而且確保它在特定索引下顯示已被渲染過的每一個元素
這個默認的模式是高效的,可是隻適用於不依賴子組件狀態或臨時DOM狀態(如表單輸入值)的列表渲染輸出
爲了給Vue一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,須要爲每項提供一個惟一key
屬性。理想的key
值是每項都有惟一id。它的工做方式相似於一個屬性,因此須要用 v-bind
來綁定動態值
<div v-for="item in items" :key="item.id"> <!-- 內容 --> </div>
建議儘量使用v-for
來提供 key
,除非迭代DOM內容足夠簡單,或者要依賴於默認行爲來得到性能提高。key是Vue識別節點的一個通用機制,key
並不特別與v-for
關聯