本文詳細介紹了 Vue 各種指令的用法,以及部分指令之間的對比
本文綱領: 本文會詳細介紹 vue 以下指令 及其 語法、用法,以及 指令之間的詳細對比,涉及指令有:
v-text,v-html,v-if,v-else,v-else-if,v-show,v-for,v-on,v-bind、v-model,v-pre,v-cloak,v-once
插值表示式(以此引出指令)
- 資料繫結最常見的形式就是
“Mustache”語法 (雙大括號)
的文字插值,Mustache
標籤將會被對應資料物件上屬性的值替代。只要繫結的資料物件上屬性發生了改變,插值處的內容都會更新。 - 用過 vue 的盆友都清楚,
message
是將資料解析成純文字的,也就是說,就算message
中含有了 html 標籤,它也是隻看做純文字的,不能輸出真正的 html。 - 例如:
<div id="app"> <p>{{message}}</p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { message: '<h1>asc</h1>' } }) </script> <!--頁面顯示為: <h1>asc</h1>-->
v-text
v-text
簡介:v-text
與插值表示式相同的地方是,它也是將資料解析成純文字(解釋html標籤可能導致xss攻擊)- 但它與花括號的區別是: 使用
v-text
在頁面載入時不會顯示'message',解決了插值表示式閃爍問題,因為他是屬性而不是插值表示式
- 例如:
<div id="app"> <p v-text="msg">這裡的內容會被替換</p> </div> <script> var vm = new Vue({ el: "#app", data: { msg: "Hello! <h1>v-text</h1>", } }) </script> <!--頁面顯示為: Hello! <h1>v-text</h1>-->
- 注: "頁面閃爍" 指的是在載入插值表示式時,會先直接在頁面顯示'message',然後再編譯對應的資料
v-html
- 簡介: 為了輸出真正的HTML,可以用v-html指令。它等同於JS的innerHtml屬性,會將資料解析成html形式。
- 例如:
<div id="app"> <p v-text="msg">這裡的內容會被替換</p> </div> <script> var vm = new Vue({ el: "#app", data: { msg: "Hello! <h1>v-html</h1>", } }) </script> <!--頁面顯示為: Hello! v-html -->
v-if
- 簡介:
v-if
指令用於條件性地渲染一塊內容。這塊內容只會在指令的表示式返回 truthy 值的時候被渲染。 - 例如:
<div id="app"> <p v-if="true"> v-if 為 true 時顯示</p> <p v-if="false"> v-if 為 false 時顯示</p> </div> <script> var vm = new Vue({ el: "#app", data: { true: true, false: false, } }) </script>
v-if
是“真正”的條件渲染,因為它會確保在切換過程中 條件塊內的事件監聽器 和 子元件 適當地被銷燬和重建。v-if
是惰性的,如果初始渲染時條件為 假,那麼就什麼也不用做,直到第一次條件變為 真,才開始渲染條件塊。v-if
通常用於以下兩種情況:- 多個元素之間,通過條件判斷,來 展示 或者 隱藏 某個或多個元素。
- 進行兩個檢視的切換。
- 例如下面的程式碼分別實現了: ①type不同值時元素的展示情況;②點選按鈕切換檢視
<div id="app"> <div style="color:red">v-if的簡單實用</div> <template> <div v-if="type == 'A'">A</div> <div v-else-if="type=='B'">B</div> <div v-else>C</div> </template> <div> <p>v-if的彈框切換</p> </div> <template v-if="loginType === 'username'"> <label>使用者名稱: </label> <input placeholder="Enter your username" key="username-input"> </template> <template v-else> <label>密碼: </label> <input placeholder="Enter your email address" key="email-input"> </template> <button @click="changeloginType">切換狀態</button> </div> <script> var app = new Vue({ el: '#app', data: { type: 'C', loginType: 'username' }, methods: { changeloginType() { let self = this; if (self.loginType == 'username') { self.loginType = '' } else { self.loginType = 'username' } } } }) </script>
- 擴充瞭解 — 官方文件: 條件渲染 — Vue.js
v-else
- 簡介: 個人感覺
v-else
並不像一個單獨功能的指令,而是偏輔助功能的,而且v-else
必須和v-if
連用,否則會報錯。 - 例如:
<div id="app"> <p v-if="msg1">The msg1 is true</p> <p v-else>The msg1 is false</p> <input type="button" @click="button" value="Button"/> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { msg1: true, }, methods: { button: function(){ this.msg1 = !this.msg1; } } }) </script>
- 上述過程即為
v-if
與v-else
連用,若去掉v-if
部分,則報錯為: 編譯模板時出錯
- 上述過程即為
v-else-if
- 簡介: 與
v-else
相同,v-else-if
也必須和v-if
連用,其實道理很簡單,類比 C語言的if
、else
、else if
,這裡的v-else-if
也是用在v-if
和v-else
中間,實現多次判斷 - 例如:
<div id="app"> <p v-if="10>20">v-if 贏了</p> <p v-else-if="10>5">v-else-if 贏了</p> <p v-else>好吧,v-else 贏了</p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', }) </script>
- 如果沒有
v-if
,那麼也會和上面的v-else
一樣報錯: 編譯模板時出錯
- 如果沒有
v-show
- 簡介:
v-show
也是用來 控制元素是否顯示 的,其功能與v-if
指令相似。 - 例如:
<div id="app"> <p v-show="msg">顯示成功</p> <input type="button" @click="show" value="Do you want to hide it?" /> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { msg: true, }, methods: { show: function(){ this.msg = !this.msg; } } }) </script>
- 那麼,
v-show
與v-if
有什麼 聯絡 呢?v-show
與v-if
都是通過 動態地操作DOM 來實現顯示與隱藏的
v-show
與v-if
的 區別 是什麼呢?- 手段的不同:
v-if
是動態地向DOM樹內動態地新增或刪除DOM元素,如果v-if
的值是false
就會在DOM中刪除,相當於visibility:hidden;
,如果是true
把元素克隆到相應的DOM樹上去,支援加在<template>
標籤上;而v-show
是動態地設定DOM元素的display
屬性,而不會刪除DOM元素,是display:none;
,不支援加在<template>
標籤上。 - 編譯過程的不同:
v-if
在切換時會有一個區域性編譯/解除安裝的過程,在切換時適當地銷燬和重建內部的事件監聽 和 子元件,因為v-if
可能是資料繫結或者子元件;而v-show
只是簡單地進行 CSS 屬性的切換。 - 編譯條件的不同:
v-if
是真真正正的條件渲染,但它是惰性的,如果初始條件為假,則什麼也不用做,只有在第一次條件變為真時才開始區域性編譯,編譯會被快取,之後等到再切換時再進行區域性解除安裝;而v-show
不管其值是否為真,都進行編譯,然後編譯被快取,而且DOM元素也保留。 - 效能消耗不同:
v-if
有著更高的切換消耗,v-show
有著更高的初識渲染消耗
由此,就引發出了使用問題:- 當元件的某塊內容切換很少,那麼切換消耗也就很少,此時用
v-if
來渲染更加合適 - 如果頻繁地切換著條件,那麼就用
v-show
更加合適,實現一次渲染,多次切換 - 為什麼這麼說呢,因為頻繁操作DOM會很影響效能,如果頻繁切換,就意味著頻繁地建立、刪除DOM,為減少消耗就更該用
v-show
;如果是要麼顯示要麼隱藏的情況下,那麼v-if
更加合理,因為藉助v-if
的惰性,如果一開始它的值即為false,那麼甚至都不需要建立DOM,如果其值為true,則效果與v-show
完全一樣。
- 當元件的某塊內容切換很少,那麼切換消耗也就很少,此時用
- 補充:
display:none
與visibility:hidden
的區別:display:none
是徹底消失,不在文件流中佔位,瀏覽器也不會解析該元素;visibility:hidden
可以理解為透明度為0的效果,它只是視覺上的消失,在文件流中是佔位的,瀏覽器也會解析該元素。- 使用
visibility:hidden
要比display:none
效能更好,用display
切換時,頁面會產生 迴流 (當頁面中的一部分元素需要改變規模尺寸、佈局、顯示隱藏等,頁面需要 重新構建,即為迴流。所有頁面第一次載入時需要產生一次迴流),而用visibility
切換時不會產生迴流。
- 補充: 若一個元素在CSS中已設定
display:none
,則無法通過設定v-if
或者v-show
來讓元素顯示,因為切換時只會修改元素 element.style 的“display”屬性為“none”或者“block”,並不會覆蓋或者修改已經存在的CSS屬性
- 手段的不同:
v-for
v-for
迴圈普通陣列:<div id="app"> <p v-for="value in list">{{value}}</p> <p v-for="(value,i) in list">索引: {{i}} => 值: {{value}}</p> <!-- 注意: 值與索引的順序為 : (value,i) --> </div> <script type="text/javascript"> var vm = new Vue({ el: "#app", data: { list: [1,2,3,4,5] } }) </script>
v-for
迴圈物件陣列:<div id="app"> <p v-for="(value,i) in list"> 索引: {{i}} —— Id: {{value.id}} —— Name: {{value.name}} </p> </div> <script type="text/javascript"> var vm = new Vue({ el: "#app", data: { list: [ { id: 1, name: 'first' }, { id: 2, name: 'second' }, { id: 3, name: 'third' }, ] } }) </script>
v-for
迴圈物件:<div id="app"> <p v-for="(value,key,i) in student"> 索引: {{i}} —— 鍵: {{key}} —— 值: {{value}} </p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { student: { id: 0, name: 'Tom', gender: '男' } } }) </script>
v-for
迭代數字:<div id="app"> <p v-for="count in 10">這是第{{count}}次迴圈</p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', }) </script>
v-for
中的key
屬性的使用:<div id="app"> <div> <label>Id: <input type="text" v-model="id" /> </label> <label>Name: <input type="text" v-model="name" /> </label> <input type="button" @click="add" value="新增" /> </div> <p v-for="item in list" :key='item.id'> <input type="checkbox" />{{item.id}} --- {{item.name}} </p> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', data: { id: '', name: '', list: [ { id: 1, name: '李斯' }, { id: 2, name: '嬴政' }, { id: 3, name: '趙高' }, ] }, methods: { add(){ this.list.unshift({ id: this.id, name: this.name }); } } }) </script>
v-on
- 簡介: 它是來 繫結事件監聽器 的,這樣我們就可以進行一下互動。
- 例如:
<div id="app"> <input type="button" v-on:click="click" value="點此彈出語句"/> </div> <script type="text/javascript"> var app = new Vue({ el: '#app', methods: { click(){ alert('Hello Vue!'); } } }) </script>
v-on
可簡寫為@
v-bind
- 簡介:
v-bind
指令主要用於 繫結屬性,可以動態地繫結一個或多個屬性,比如 class屬性、style屬性、value屬性、href屬性,只要是屬性,就可以用v-bind
進行繫結。它的語法是:v-bind:屬性名 = "變數名"
,規定v-bind
可以縮寫為:
,如語法可以縮寫為:屬性名 = "變數名"
。 - 繫結 HTML Class:
- 物件語法: 我們可以傳給
v-bind:class
一個物件,以動態地切換 class屬性,如:<div v-bind:class="{ active: isActive }"></div> <script> var vm = new Vue({ el: '#app', data: { isActive: true //此時可以展示active } }) </script>
- 上述表示 active 是否被展現取決於 isActive 是否為真。
- 此外,可以在物件中傳入多個屬性來動態地切換 class,例如下面的模板:
<div class="static" v-bind:class="{ A:isA, 'B': isB }"></div> <script> var vm = new Vue({ el: '#app', data: { isA: true, isB: false, } }) //結果渲染為: <div class="static isA"></div> </script>
- 當然,繫結的物件也不必內聯定義在模板裡,而是用一個物件名代替:
<div v-bind:class="classObject"></div> <script> var vm = new Vue({ el: '#app', data: { classObject{ isA: true, isB: false, } } }) </script>
- 我們也可以繫結一個返回物件的計算屬性,這是一個強大而且常用的模式:
<div v-bind:class="classObject"></div> <script> var vm = new Vue({ el: '#app', data: { isA: true, isB: false, }, computed: { classObject: function () { return { active: this.isA && !this.isB, statiq: this.isB && this.isB.type === 'fatal' } } } }) </script>
- 陣列語法: 我們可以把一個陣列傳給
v-bind:class
,以應用一個 class列表:<div id="app"> <div v-bind:class="[activeClass, errorClass]"></div> </div> <script> var vm = new Vue({ el: '#app', data: { activeClass: 'active', errorClass: 'text-danger' } }) //渲染為 <div class="active text-danger"></div> </script>
- 物件語法: 我們可以傳給
- 注: 關於
v-bind
指令詳解請參考: 詳解v-bind指令 以及 vue.js中的v-bind語法的使用詳解
v-model
- 簡介: 這個指令用於 在表單上建立雙向資料繫結,
v-model
會忽略所有表單元素的 value、checked、selected特性的初始值,因為v-model
選擇Vue例項資料來作為具體的值。 - 例如:
<div id="app"> <input v-model="somebody"> <p>hello {{somebody}}</p> </div> <script> var app = new Vue({ el: '#app', data: { somebody: '小明' } }) </script>
v-pre
- 簡介:
v-pre
會 按原樣輸出,標籤中的內容是什麼就輸出什麼,主要用來跳過這個元素以及它的子元素的編譯過程,可以用來顯示原始的Mustache標籤。 - 例如:
<div id="app"> <p v-pre>{{msg}}</p> <p>{{msg}}</p> </div> <script> var app = new Vue({ el: '#app', data: { msg:"'v-pre'是不會管我的..." } }) </script>
v-cloak
- 簡介: 還記得上文中提到的 頁面閃爍 嗎,我們也可以用
v-cloak
來解決這一問題。
這個指令用來保持在元素上直到關聯例項結束時進行編譯。 - 例如:
<div id="app" v-cloak> {{context}} </div> <script> var app = new Vue({ el: '#app', data: { context:'Hello Vue!' } }); //用'v-cloak'則不會出現閃爍 </script>
v-once
v-once
關聯的例項 只會渲染一次,執行 一次性地插值,當資料改變時,插值處的內容不會更新,v-once所定義的元素或元件只會渲染一次,首次渲染後,不再隨著資料的改變而重新渲染。若之後牽涉到重新渲染,那麼 它關聯的例項及其所有子節點 會被視為 靜態內容 而被跳過,這可以用來優化更新效能。- 例如:
<div id="app"> <p v-once>{{msg}}</p> <p>{{msg}}</p> <p> <input type="text" v-model="msg" name=""> </p> </div> <script type="text/javascript"> var vm = new Vue({ el: '#app', data: { msg: "hello" } }); </script>