最近有時間來總結一下vue的知識:css
1、vue.js 被定義成一個開發web界面的前端庫,是一個很是輕量的工具。vue.js自己具備響應式和組件化的特色。html
咱們不須要在維護視圖和數據的統一上花費大量的時間,只須要關注於 data 的變化,代碼變得更加容易維護。前端
可是要選擇框架仍是要根據實際狀況。vue
理想的狀況下,vue更適合作先後端分離的項目。web
2、vue的基礎特性(不管前端框架怎麼變化,它須要處理的事情依舊是模板渲染、事件綁定、處理用戶交互(輸入信息或者鼠標操做))ajax
vue.js是經過一個實例new Vue({.....})標記當前頁面的HTML結構、數據的展現及相關事件的綁定。 vue.js的構造函數的選項對象及用法,以及如何經過vue.js來實現上述前端功能。正則表達式
1.實例及選項編程
1.1模板json
1.2數據後端
1.3方法
1.4生命週期
2.數據綁定
2.1數據綁定語法
2.1.1文本插值
2.1.2HTML屬性
2.1.3綁定表達式
2.1.4過濾器
2.1.5指令
2.2計算屬性
2.3表單控件
2.4class與style綁定
3.模板渲染
3.1先後端渲染對比
3.2條件渲染
3.3列表渲染
3.4template標籤用法
4.事件綁定與監聽
4.1方法及內聯語句處理器
4.2修飾符
4.3與傳統事件綁定的區別
5.vue.extend()
1.實例及選項
vue.js的使用都是經過構造函數Vue({option})建立一個vue的實例:var vm = new Vue({})。一個Vue實例至關於一個MVVM模式中的ViewModel.
在實例化的時候,咱們能夠傳入一個選項對象,包含數據、模板、掛載元素、方法、生命週期鉤子等選項。
1.1模板
選項中主要影響模板或DOM的選項有el和template。
el:類型爲字符串,DOM元素或函數。其做用是爲實例提供掛載元素。通常來講,咱們會選用css選擇符,或者原生的DOM元素。
提供一個在頁面上已存在的 DOM 元素做爲 Vue 實例的掛載目標。能夠是 CSS 選擇器,也能夠是一個 HTMLElement 實例。
在實例掛載以後,元素能夠用 vm.$el
訪問。
若是這個選項在實例化時有做用,實例將當即進入編譯過程,不然,須要顯式調用 vm.$mount()
手動開啓編譯。
template:類型爲字符串。默認會將template值替換掛載元素(即el值對應的元素),併合並掛載元素和模板根節點的屬性。
一個字符串模板做爲 Vue 實例的標識使用。模板將會 替換 掛載的元素。掛載元素的內容都將被忽略,除非模板的內容有分發插槽。
render:字符串模板的代替方案,容許你發揮 JavaScript 最大的編程能力。
該渲染函數接收一個 createElement
方法做爲第一個參數用來建立 VNode
。
若是組件是一個函數組件,渲染函數還會接收一個額外的 context
參數,爲沒有實例的函數組件提供上下文信息。
rendererror:只在開發者環境下工做。
當 render
函數遭遇錯誤時,提供另一種渲染輸出。其錯誤將會做爲第二個參數傳遞到 renderError
。這個功能配合 hot-reload 很是實用。
new Vue({
render (h) {
throw new Error('oops')
},
renderError (h, err) {
return h('pre', { style: { color: 'red' }}, err.stack)
}
}).$mount('#app')
1.2數據
Vue實例的數據對象。Vue將會遞歸將data的屬性轉換爲getter/setter,從而讓打他的屬性可以響應數據變化。對象必須是純粹的對象(含有零個或多個的key/value對):瀏覽器API建立的原生對象,原型上的屬性會被忽略。大概來講,data應該只能是數據-不推薦觀察擁有狀態行爲的對象。
一旦觀察過,不須要再次在數據對象上添加響應式屬性。所以推薦在建立實例以前,就聲明全部的根級響應式屬性。
實例建立以後,能夠經過vm.$data訪問原始數據對象。Vue實例也代理了data對象上全部的屬性,所以訪問vm.a等價於訪問vm.$data.a。
以 _ 或$ 開頭的屬性不會被Vue實例代理,由於他們可能和Vue內置的屬性、API方法衝突。你可使用例如vm.$data._property的方式訪問這些屬性。
當一個組件被定義,data必須聲明爲返回一個初始數據對象的函數,由於組件可能被用來建立多個實例。若是data仍然是一個純粹的對象,則全部的實例將共享引用同一個數據對象!經過提供data函數,每次建立一個新實例後,咱們可以調用data函數,從而返回初始數據的一個全新副本數據對象。
若是須要,能夠經過將vm.$data傳入JSON.parse(JSON.stringify(...))獲得深拷貝的原始數據對象。
1 var data = { a: 1 } 2 3 // 直接建立一個實例 4 var vm = new Vue({ 5 data: data 6 }) 7 vm.a // => 1 8 vm.$data === data // => true 9 10 // Vue.extend() 中 data 必須是函數 11 var Component = Vue.extend({ 12 data: function () { 13 return { a: 1 } 14 } 15 })
注意:若是你爲data屬性使用了箭頭函數,則this不會指向這個組件的實例,不過你仍然能夠將其實例做爲函數的第一個參數來訪問。
data: vm => ({ a: vm.myProp })
Vue.js實例中能夠經過data屬性定義數據,這些數據能夠在實例對應的模板中進行綁定並使用。須要注意的是,若是傳入data的是一個對象,vue實例會代理起data對象的全部屬性,而不會對傳入的對象進行深拷貝。另外,咱們也能夠引用Vue實例vm中的$data來獲取聲明的數據。
1 var data = { a: 1 } 2 var vm = new Vue({ 3 data: data 4 }) 5 vm.$data === data // -> true 6 vm.a === data.a // -> true 7 // 設置屬性也會影響到原始數據 8 vm.a = 2 9 data.a // -> 2 10 // 反之亦然 11 data.a = 3 vm.a // -> 3
須要注意的是,只有初始化時傳入的對象纔是響應式的。因此,咱們應儘可能在初始化的時候,把全部的變量都設定好,若是沒有值,也能夠用undefined或null佔位。另外,組件類型的實例能夠經過props獲取數據,通data同樣,也須要在初始化時預設好。
1.3方法
methods將被混入到vue實例中。能夠直接經過vm實例訪問這些方法,或者在指令表達式中使用。方法中的this自動綁定爲Vue實例。
注意:不該該使用箭頭函數來定義method函數(例如plus:()=> this.a++)。理由是箭頭函數綁定了父級做用域的上下文,因此this將不會按照指望指向Vue實例,this.a將是undefined。
1 var vm = new Vue({ 2 data: { a: 1 }, 3 methods: { 4 plus: function () { 5 this.a++ 6 } 7 } 8 }) 9 vm.plus() 10 vm.a // 2
咱們能夠經過選項屬性methods對象來定義方法,並使用v-on指令來監聽DOM事件。
1 <button v-on:click="alert"/>alert<button> new Vue({ 2 el : '#app', 3 data : { a : 1}, 4 methods : { 5 alert : function() { alert(this.a); } 6 } 7 });
1.4生命週期
下圖展現了實例的生命週期。你不須要立馬弄明白全部的東西,不過隨着你的不斷學習和使用,它的參考價值會愈來愈高。
$el
屬性目前不可見。render
函數首次被調用。該鉤子在服務器端渲染期間不被調用。el
被新建立的 vm.$el
替換,並掛載到實例上去以後調用該鉤子。若是 root 實例掛載了一個文檔內元素,當 mounted
被調用時 vm.$el
也在文檔內。該鉤子在服務器端渲染期間不被調用。注意 mounted
不會承諾全部的子組件也都一塊兒被掛載。若是你但願等到整個視圖都渲染完畢,能夠用 vm.$nextTick 替換掉 mounted
:
1 mounted: function () { 2 this.$nextTick(function () { 3 // Code that will run only after the 4 // entire view has been rendered 5 }) 6 }
當這個鉤子被調用時,組件 DOM 已經更新,因此你如今能夠執行依賴於 DOM 的操做。然而在大多數狀況下,你應該避免在此期間更改狀態。若是要相應狀態改變,一般最好使用計算屬性或 watcher 取而代之。該鉤子在服務器端渲染期間不被調用。
注意 updated
不會承諾全部的子組件也都一塊兒被重繪。若是你但願等到整個視圖都重繪完畢,能夠用 vm.$nextTick 替換掉 updated
:
1 updated: function () { 2 this.$nextTick(function () { 3 // Code that will run only after the 4 // entire view has been re-rendered 5 }) 6 }
false
以阻止該錯誤繼續向上傳播。你能夠在此鉤子中修改組件的狀態。所以在模板或渲染函數中設置其它內容的短路條件很是重要,它能夠防止當一個錯誤被捕獲時該組件進入一個無限的渲染循環。
錯誤傳播規則
默認狀況下,若是全局的 config.errorHandler 被定義,全部的錯誤仍會發送它,所以這些錯誤仍然會向單一的分析服務的地方進行彙報。
若是一個組件的繼承或父級從屬鏈路中存在多個 errorCaptured 鉤子,則它們將會被相同的錯誤逐個喚起。
若是此 errorCaptured 鉤子自身拋出了一個錯誤,則這個新錯誤和本來被捕獲的錯誤都會發送給全局的 config.errorHandler。
一個 errorCaptured 鉤子可以返回 false 以阻止錯誤繼續向上傳播。本質上是說「這個錯誤已經被搞定了且應該被忽略」。它會阻止其它任何會被這個錯誤喚起的 errorCaptured 鉤子和全局的 config.errorHandler。
1 var vm = new Vue({ 2 el : '#app', 3 init: function() { 4 console.log('init'); }, 5 created: function() { 6 console.log('created'); 7 }, 8 beforeCompile: function() { console.log('beforeCompile'); }, 9 compiled: function() { 10 console.log('compiled'); 11 }, 12 attached: function() { 13 console.log('attached'); }, 14 dettached: function() { 15 console.log('dettached'); }, 16 beforeDestroy: function() { console.log('beforeDestroy'); }, 17 destroyed: function() { 18 console.log('destroyed'); }, 19 ready: function() { 20 console.log('ready'); 21 // 組件完成後調用$destory()函數,進行銷燬 22 this.$destroy(); } 23 });
輸出結果爲:
2.數據綁定
2.1數據綁定語法
1 var vm = new Vue({ el : '#app', 2 data: { 3 id:1, 4 index : 0, 5 name : 'Vue', 6 avatar : 'http://......' 7 count:[1,2,3,4,5] 8 names : ['Vue1.0', 'Vue2.0'], items:[ 9 { name : 'Vue1.0', version : '1.0' }, 10 { name : 'Vue1.1', version : '1.0' } 11 ] 12 } 13 });
2.1.1文本插值
數據綁定最基礎的形式就是文本插值,使用的是雙大括號{{}}。
vue.js實例vm中name屬性的值將會替換Mustache標籤中的name,而且修改數據對象中的name屬性,DOM也會隨之更新。
2.1.2HTML屬性
Museache標籤也一樣適用於HTML屬性中。
<div v-bind:id="'id-'+id"></div> 簡寫爲<div :id="'id-' + id"></div>
2.1.3綁定表達式
放在Mustache標籤內的文本內容稱爲綁定表達式。
除了直接輸出屬性值以外,一段綁定表達式能夠由一個簡單的JavaScript表達式和可選的一個或多個過濾器構成。
每一個綁定中只能包含單個表達式,並不支持JavaScript語句。
而且綁定表達式裏不支持正則表達式,若是須要進行復雜的轉換,可使用過濾器或者計算屬性來進行處理。
2.1.4過濾器
vue.js容許在表達式後添加可選的過濾器,以管道符「|」指示。
vue.js內置了10個過濾器:
>1.capitalize:字符串首字符轉化成大寫
>2.uppercase:字符串轉化成大寫
>3.lowercase:字符串轉化成小寫
>4.currency參數爲{string}[貨幣符號],{Number}[小數位],將數字轉化成貨幣符號,而且會自動添加數字分節號。
{{ amount | cyrrency '¥' 2 }} //->若amount=1000,則輸出¥1,000.00
>5.pluralize參數爲{String}single,[double, triple],字符串複數化。若是接受的是一個參數,那複數形式就是在字符串末尾直接加一個「s」。
若是接受多個參數,則會被當成數組處理,字符串會添加對應數組下標的值。
若是字符串的個數多於參數個數,多出部分會都添加最後一個參數的值。
<p v-for="c in count">{{ c | pluralize 'item' }} {{ c | pluralize 'st' 'nd' 'rd' 'th' }}</p>
>6.json參數爲{Number}[indent]空格縮進數,與JSON.stringify()做用相同,將json對象數據輸出成符合json格式的字符串。
>7.debounce傳入值必須是函數,參數可選,爲{Number}[wait],即延時時長。
做用是當調用函數n毫秒後,纔會執行該動做,若在這n毫秒內又調用此動做則將從新計算執行時間。
<input v-on:keyup="onKeyup | debounce 500"> //input元素上監聽了keyup事件,而且延遲500ms觸發。
>8.limitBy傳入值必須是數組,參數爲{Number}limit,{Number}[offset],limit爲顯示個數,offset爲開始顯示數組下標。
<div v-for="item in items | limitBy 10"></div> //items爲數組,且只顯示數組中的前十個元素。
>9.filterBy傳入值必須是數組,參數爲{String | Function}targetStringOrFunction,
即須要匹配的字符串或函數(經過函數返回值true或false來判斷匹配結果);
「in」(可選分隔符);{String}[...searchKeys],爲檢索的屬性區域。
<p v-for="name in names | filterBy '1.0'">{{name}}</p> //檢索items數組中值包含1.0的元素
<p v-for="item in items | filterBy '1.0' in 'name'">{{ item | json }}</p> //檢索items數組中元素屬性值爲1.0的元素輸出。檢索區域也能夠爲數組
即in[name, version],在多個屬性中進行檢索。
<p v-for="item in items | filterBy customFilter">{{ item | json }}</p> //使用自定義的過濾函數,函數能夠在選項methods中定義
methods: {
customFilter : function(item){
if(item.name) return true //檢索全部元素中包含name屬性的元素
}
}
>10.orderBy 傳入值必須是數組,參數爲{String | Array | Function }sortKeys,即指定排序策略。
這裏可使用單個鍵名,也能夠傳入包含多個排序鍵名的數組。也能夠像Array.Sort()那樣傳入本身的排序策略函數。
第二個參數爲可選參數{String}[order], 即選擇升序或降序,order>=0爲升序,order<0爲降序。
單個鍵名:<p v-for="item in items | orderBy 'name' -1 ">{{item.name}}</p> //items數組中以鍵名name進行降序排序
多個鍵名:<p v-for="item in items | orderBy [name, version]">{{item.name}}</p> //使用items裏的兩個鍵名進行排序
自定義排序函數:<p v-for="item in items | orderBy curtomOrder">{{item.name}}</p>
methods : {
customOrder : function (a, b) {
return parseFloat(a.version) > parseFloat(b.version) //對比item中version的值的大小進行排序
}
}
2.1.5指令
能夠理解爲當表達式的值發生變化時,會有些特殊行爲做用到綁定的DOM上。
指令一般會直接書寫在模板的HTML元素中,而爲了有別於普通的屬性, Vue.js指令是帶有前綴的v-的屬性上。
指令值限定爲綁定表達式,JavaScript表達式以及過濾器規則在這裏也適用。
2.1.5.1參數
<img v-bind:src="avatar"> //指令v-bind能夠在後面帶一個參數,用冒號(:)隔開,src即爲參數。
此時img標籤中的src會與vm實例中的avatar綁定,等同於<img src="{{avatar}}"/>
2.1.5.2修飾符
修飾符是以半角句號.開始的特殊後綴,用於表示指令應該以特殊方式綁定。<button v-on:click.stop="doClick"></button>
v-on的做用是在對應的DOM元素上綁定事件監聽器,doClick爲函數名,而stop即爲修飾符,
做用是中止冒泡,至關於調用了e.stopPropagation()。
2.2計算屬性
避免在模板中加入太重的業務邏輯,保證模板的結構清晰和可維護性。
2.2.1基礎例子
var vm = new Vue({
el : '#app',
data : {
firstName : 'Gavin',
lastName : 'CLV'
}
computed : {
fullName : function(){
return this.fristName + ' ' + this.lastName
}
}
});
<p>{{ firstName }}</p> //Gavin
<p>{{ lastName }}</p> //CLY
<p>{{ fullName }}</p> //Gavin CLY
此時,你對vm.firstName和vm.lastName進行修改,始終會影響vm.fullName.
2.2.2Setter
var vm = new Vue({
el : '#el',
data : {
cents : 100,
}
computed : {
price : {
set : function(newValue){
this.cents = newValue * 100;
},
get : function(){
return(this.cents/100).toFixed(2);
}
}
}
});
在處理商品價格的時候,後端每每會把價格定義成以分爲單位的整數,避免在處理浮點類型數據時產生的問題。
而前端則須要把價錢再轉換成元進行展現,並且若是須要對價錢進行修改的話,則又要把輸入的價格再恢復到分傳給後端,非常繁瑣。
而在使用vue的計算屬性後,咱們能夠將vm.cents設置爲後端所存的數據,計算屬性price爲前端展現和更新的數據。
<p>¥{{price}}</p> //¥1.00
此時更改vm.price = 2, vm.cents會被更新爲200,在傳遞給後端時無需再手動轉化一遍數據。
2.3表單控件
Vue.js中提供v-model的指令對錶單元素進行雙向數據綁定,在修改表單元素值的同時,實例vm中對應的屬性值也同時更新,反之亦然。
var vm = new Vue({
el : '#app',
data : {
message : '',
gender : '',
checked : '',
multiChecked : [],
selected : '',
multiSelected: []
}
});
2.3.1Text :輸入框
用戶輸入的內容和vm.message直接綁定:
<input type="text" v-model="message"/>
<span>Your input is : {{ message }}</span>
2.3.2Radio :單選框
<label><input type="radio" value="male" v-model="gender">男</label>
<label><input type="radio" value="female" v-model="gender">女</label>
2.3.3Checkbox
checkbox分兩種狀況:單個勾選框和多個勾選框。
單個勾選框,v-model即爲布爾值,此時input的value並不影響v-model的值。
<input tyep="checkbox" v-model="checked"/>
<span>checked : {{ checked }}</span>
多個勾選框,v-model使用相同的屬性名稱,且屬性爲數組。
<label><input type="checkbox" value="1" v-model="multiChecked">1</label>
<label><input type="checkbox" value="2" v-model="multiChecked">2</label>
<label><input type="checkbox" value="3" v-model="multiChecked">3</label>
<p>MultiChecked: {{ multiCheched.join('|') }}</p>
2.3.4Select
單選:
<select v-model="selected">
<option selected>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
多選:
<select v-model="multiSelected" multiple>
<option selected>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>MultiSelected: {{ multiCheched.join('|') }}</span>
2.3.5綁定value
表單控件的值一樣能夠綁定Vue實例的動態屬性上,用v-bind實現。
1.Checkbox
<input type="checkbox" v-model="checked" v-bind:true-value="a" v-bind:false-value="b">
選中:vm.checked == vm.a // ->true
未選中:vm.checked == vm.b // ->false
2.Radio
<input type="radio" v-model="checked", v-bind:value="a">
選中:vm.checked == vm.a // ->true
3.Select Options
<select v-model="seleced">
<option v-bind:value="{ number : 123 }">123</option>
</select>
選中:
typeof vm.selected // ->'object'
vm.selected.number //->123
2.3.6參數特性
Vue.js爲表單控件提供了一些參數,方便處理某些常規操做。
2.3.6.一、lazy
默認狀況下,v-model在input事件中同步輸入框值與數據,加lazy屬性後從會改到在change事件中同步
<input v-model="query" lazy/>
2.3.6.二、number
會自動將用戶輸入轉爲Number類型,若是原值轉換結果爲NaN則返回原值。
<input v-model="age" number/>
2.3.6.三、debounce
debounce爲設置的最小延時,單位爲ms,即爲單位時間內僅執行一次數據更新。
該參數每每應用在高耗操做上,例如在更新時發出ajax請求返回提示信息。
<input v-model="query" debounce="500"/>
不過vue.js2.0中取消了lazy和number做爲參數,用修飾符來代替
2.4class與style綁定
操做元素的 class 列表和內聯樣式是數據綁定的一個常見需求。
由於它們都是屬性,因此咱們能夠用 v-bind
處理它們:只須要經過表達式計算出字符串結果便可。
不過,字符串拼接麻煩且易錯。所以,在將 v-bind
用於 class
和 style
時,Vue.js 作了專門的加強。
表達式結果的類型除了字符串以外,還能夠是對象或數組。
2.4.一、class綁定
咱們能夠傳給 v-bind:class
一個對象,以動態地切換 class:
<div v-bind:class="{ active: isActive }"></div> |
上面的語法表示 active
這個 class 存在與否將取決於數據屬性 isActive
的 truthiness。
你能夠在對象中傳入更多屬性來動態切換多個 class。此外,v-bind:class
指令也能夠與普通的 class 屬性共存。當有以下模板:
<div class="static" |
和以下 data:
data: { |
結果渲染爲:
<div class="static active"></div> |
當 isActive
或者 hasError
變化時,class 列表將相應地更新。
例如,若是 hasError
的值爲 true
,class 列表將變爲 "static active text-danger"
。
綁定的數據對象沒必要內聯定義在模板裏:
<div v-bind:class="classObject"></div> |
data: { |
渲染的結果和上面同樣。咱們也能夠在這裏綁定一個返回對象的計算屬性。這是一個經常使用且強大的模式:
<div v-bind:class="classObject"></div> |
data: { |
v-bind:class
,以應用一個 class 列表: <div v-bind:class="[activeClass, errorClass]"></div> |
data: { |
渲染爲:
<div class="active text-danger"></div> |
若是你也想根據條件切換列表中的 class,能夠用三元表達式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div> |
這樣寫將始終添加 errorClass
,可是隻有在 isActive
是 truthy[1] 時才添加 activeClass
。
不過,當有多個條件 class 時這樣寫有些繁瑣。因此在數組語法中也可使用對象語法:
<div v-bind:class="[{ active: isActive }, errorClass]"></div> |
這個章節假設你已經對 Vue 組件有必定的瞭解。固然你也能夠先跳過這裏,稍後再回過頭來看。
當在一個自定義組件上使用 class
屬性時,這些類將被添加到該組件的根元素上面。這個元素上已經存在的類不會被覆蓋。
例如,若是你聲明瞭這個組件:
Vue.component('my-component', { |
而後在使用它的時候添加一些 class:
<my-component class="baz boo"></my-component> |
HTML 將被渲染爲:
<p class="foo bar baz boo">Hi</p> |
對於帶數據綁定 class 也一樣適用:
<my-component v-bind:class="{ active: isActive }"></my-component> |
當 isActive
爲 truthy[1] 時,HTML 將被渲染成爲:
<p class="foo bar active">Hi</p>
|
2.4.二、內聯樣式綁定
對象語法
v-bind:style
的對象語法十分直觀——看着很是像 CSS,但實際上是一個 JavaScript 對象。
CSS 屬性名能夠用駝峯式 (camelCase) 或短橫線分隔 (kebab-case,記得用單引號括起來) 來命名:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> |
data: { |
直接綁定到一個樣式對象一般更好,這會讓模板更清晰:
<div v-bind:style="styleObject"></div> |
data: { |
一樣的,對象語法經常結合返回對象的計算屬性使用。
v-bind:style
的數組語法能夠將多個樣式對象應用到同一個元素上:
<div v-bind:style="[baseStyles, overridingStyles]"></div> |
當 v-bind:style
使用須要添加瀏覽器引擎前綴的 CSS 屬性時,如 transform
,Vue.js 會自動偵測並添加相應的前綴。
多重值
2.3.0+
從 2.3.0 起你能夠爲 style
綁定中的屬性提供一個包含多個值的數組,經常使用於提供多個帶前綴的值,例如:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div> |
這樣寫只會渲染數組中最後一個被瀏覽器支持的值。在本例中,若是瀏覽器支持不帶瀏覽器前綴的 flexbox,那麼就只會渲染 display: flex
。
譯者注
[1] truthy 不是 true
,詳見 MDN 的解釋。
3.模板渲染
當獲取到後臺數據後,咱們會把它按照必定的規則加載到寫好的模板中,輸出成在瀏覽器中顯示的HTML,這個過程就稱爲渲染。
3.1先後端渲染對比
3.2條件渲染
v-if
在字符串模板中,好比 Handlebars,咱們得像這樣寫一個條件塊:
<!-- Handlebars 模板 --> |
在 Vue 中,咱們使用 v-if
指令實現一樣的功能:
<h1 v-if="ok">Yes</h1> |
也能夠用 v-else
添加一個「else 塊」:
<h1 v-if="ok">Yes</h1> |
由於 v-if
是一個指令,因此必須將它添加到一個元素上。可是若是想切換多個元素呢?
此時能夠把一個 <template>
元素當作不可見的包裹元素,並在上面使用 v-if
。最終的渲染結果將不包含 <template>
元素。
<template v-if="ok"> |
你可使用 v-else
指令來表示 v-if
的「else 塊」:
<div v-if="Math.random() > 0.5"> |
v-else
元素必須緊跟在帶 v-if
或者 v-else-if
的元素的後面,不然它將不會被識別。
v-else-if
2.1.0 新增
v-else-if
,顧名思義,充當 v-if
的「else-if 塊」,能夠連續使用:
<div v-if="type === 'A'"> |
相似於 v-else
,v-else-if
也必須緊跟在帶 v-if
或者 v-else-if
的元素以後。
Vue 會盡量高效地渲染元素,一般會複用已有元素而不是從頭開始渲染。
這麼作除了使 Vue 變得很是快以外,還有其它一些好處。例如,若是你容許用戶在不一樣的登陸方式之間切換:
<template v-if="loginType === 'username'"> |
那麼在上面的代碼中切換 loginType
將不會清除用戶已經輸入的內容。
由於兩個模板使用了相同的元素,<input>
不會被替換掉——僅僅是替換了它的 placeholder
。
本身動手試一試,在輸入框中輸入一些文本,而後按下切換按鈕:
這樣也不老是符合實際需求,因此 Vue 爲你提供了一種方式來表達「這兩個元素是徹底獨立的,不要複用它們」。
只需添加一個具備惟一值的 key
屬性便可:
<template v-if="loginType === 'username'"> |
如今,每次切換時,輸入框都將被從新渲染。請看:
注意,<label>
元素仍然會被高效地複用,由於它們沒有添加 key
屬性。
另外一個用於根據條件展現元素的選項是 v-show
指令。用法大體同樣:
<h1 v-show="ok">Hello!</h1> |
不一樣的是帶有 v-show
的元素始終會被渲染並保留在 DOM 中。v-show
只是簡單地切換元素的 CSS 屬性 display
。
注意,v-show
不支持 <template>
元素,也不支持 v-else
。
v-if
是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。
v-if
也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。
相比之下,v-show
就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。
通常來講,v-if
有更高的切換開銷,而 v-show
有更高的初始渲染開銷。
所以,若是須要很是頻繁地切換,則使用 v-show
較好;若是在運行時條件不多改變,則使用 v-if
較好。
當 v-if
與 v-for
一塊兒使用時,v-for
具備比 v-if
更高的優先級。
請查閱 列表渲染指南 以獲取詳細信息。
3.3列表渲染
用v-for把一個數組對應爲一組元素
咱們用 v-for
指令根據一組數組的選項列表進行渲染。
v-for
指令須要使用 item in items
形式的特殊語法,items
是源數據數組而且 item
是數組元素迭代的別名。
<ul id="example-1"> |
var example1 = new Vue({ |
結果:
在 v-for
塊中,咱們擁有對父做用域屬性的徹底訪問權限。v-for
還支持一個可選的第二個參數爲當前項的索引。
<ul id="example-2"> |
var example2 = new Vue({ |
結果:
你也能夠用 of
替代 in
做爲分隔符,由於它是最接近 JavaScript 迭代器的語法:
<div v-for="item of items"></div> |
你也能夠用 v-for
經過一個對象的屬性來迭代。
<ul id="v-for-object" class="demo"> |
new Vue({ |
結果:
你也能夠提供第二個的參數爲鍵名:
<div v-for="(value, key) in object"> |
第三個參數爲索引:
<div v-for="(value, key, index) in object"> |
在遍歷對象時,是按 Object.keys()
的結果遍歷,可是不能保證它的結果在不一樣的 JavaScript 引擎下是一致的。
當 Vue.js 用 v-for
正在更新已渲染過的元素列表時,它默認用「就地複用」策略。
若是數據項的順序被改變,Vue 將不會移動 DOM 元素來匹配數據項的順序, 而是簡單複用此處每一個元素,
而且確保它在特定索引下顯示已被渲染過的每一個元素。這個相似 Vue 1.x 的 track-by="$index"
。
這個默認的模式是高效的,可是隻適用於不依賴子組件狀態或臨時 DOM 狀態 (例如:表單輸入值) 的列表渲染輸出。
爲了給 Vue 一個提示,以便它能跟蹤每一個節點的身份,從而重用和從新排序現有元素,你須要爲每項提供一個惟一 key
屬性。
理想的 key
值是每項都有的且惟一的 id。這個特殊的屬性至關於 Vue 1.x 的 track-by
,但它的工做方式相似於一個屬性,
因此你須要用 v-bind
來綁定動態值 (在這裏使用簡寫):
<div v-for="item in items" :key="item.id"> |
建議儘量在使用 v-for
時提供 key
,除非遍歷輸出的 DOM 內容很是簡單,或者是刻意依賴默認行爲以獲取性能上的提高。
由於它是 Vue 識別節點的一個通用機制,key
並不與 v-for
特別關聯,key 還具備其餘用途,
咱們將在後面的指南中看到其餘用途。
Vue 包含一組觀察數組的變異方法,因此它們也將會觸發視圖更新。這些方法以下:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
你打開控制檯,而後用前面例子的 items
數組調用變異方法:example1.items.push({ message: 'Baz' })
。
變異方法 (mutation method),顧名思義,會改變被這些方法調用的原始數組。相比之下,也有非變異 (non-mutating method) 方法,
例如:filter()
, concat()
和 slice()
。這些不會改變原始數組,但老是返回一個新數組。當使用非變異方法時,能夠用新數組替換舊數組:
example1.items = example1.items.filter(function (item) { |
你可能認爲這將致使 Vue 丟棄現有 DOM 並從新渲染整個列表。
幸運的是,事實並不是如此。Vue 爲了使得 DOM 元素獲得最大範圍的重用而實現了一些智能的、啓發式的方法,
因此用一個含有相同元素的數組去替換原來的數組是很是高效的操做。
因爲 JavaScript 的限制,Vue 不能檢測如下變更的數組:
vm.items[indexOfItem] = newValue
vm.items.length = newLength
舉個例子:
var vm = new Vue({ |
爲了解決第一類問題,如下兩種方式均可以實現和 vm.items[indexOfItem] = newValue
相同的效果,同時也將觸發狀態更新:
// Vue.set |
// Array.prototype.splice |
你也可使用 vm.$set
實例方法,該方法是全局方法 Vue.set
的一個別名:
vm.$set(vm.items, indexOfItem, newValue) |
爲了解決第二類問題,你可使用 splice
:
vm.items.splice(newLength) |
仍是因爲 JavaScript 的限制,Vue 不能檢測對象屬性的添加或刪除:
var vm = new Vue({ |
對於已經建立的實例,Vue 不能動態添加根級別的響應式屬性。
可是,可使用 Vue.set(object, key, value)
方法向嵌套對象添加響應式屬性。例如,對於:
var vm = new Vue({ |
你能夠添加一個新的 age
屬性到嵌套的 userProfile
對象:
Vue.set(vm.userProfile, 'age', 27) |
你還可使用 vm.$set
實例方法,它只是全局 Vue.set
的別名:
vm.$set(vm.userProfile, 'age', 27) |
有時你可能須要爲已有對象賦予多個新屬性,好比使用 Object.assign()
或 _.extend()
。
在這種狀況下,你應該用兩個對象的屬性建立一個新的對象。因此,若是你想添加新的響應式屬性,不要像這樣:
Object.assign(vm.userProfile, { |
你應該這樣作:
vm.userProfile = Object.assign({}, vm.userProfile, { |
有時,咱們想要顯示一個數組的過濾或排序副本,而不實際改變或重置原始數據。
在這種狀況下,能夠建立返回過濾或排序數組的計算屬性。
例如:
<li v-for="n in evenNumbers">{{ n }}</li> |
data: { |
在計算屬性不適用的狀況下 (例如,在嵌套 v-for
循環中) 你可使用一個 method 方法:
<li v-for="n in even(numbers)">{{ n }}</li> |
data: { |
v-for
v-for
也能夠取整數。在這種狀況下,它將重複屢次模板。
<div> |
結果:
v-for
on a <template>
相似於 v-if
,你也能夠利用帶有 v-for
的 <template>
渲染多個元素。好比:
<ul> |
v-for
with v-if
當它們處於同一節點,v-for
的優先級比 v-if
更高,這意味着 v-if
將分別重複運行於每一個 v-for
循環中。
當你想爲僅有的一些項渲染節點時,這種優先級的機制會十分有用,以下:
<li v-for="todo in todos" v-if="!todo.isComplete"> |
上面的代碼只傳遞了未完成的 todos。
而若是你的目的是有條件地跳過循環的執行,那麼能夠將 v-if
置於外層元素 (或 <template>
)上。如:
<ul v-if="todos.length"> |
v-for
瞭解組件相關知識,查看 組件。徹底能夠先跳過它,之後再回來查看。
在自定義組件裏,你能夠像任何普通元素同樣用 v-for
。
<my-component v-for="item in items" :key="item.id"></my-component> |
2.2.0+ 的版本里,當在組件中使用
v-for
時,key
如今是必須的。
然而,任何數據都不會被自動傳遞到組件裏,由於組件有本身獨立的做用域。爲了把迭代數據傳遞到組件裏,咱們要用 props
:
<my-component |
不自動將 item
注入到組件裏的緣由是,這會使得組件與 v-for
的運做緊密耦合。明確組件數據的來源可以使組件在其餘場合重複使用。
下面是一個簡單的 todo list 的完整例子:
<div id="todo-list-example"> |
注意這裏的 is="todo-item"
屬性。這種作法在使用 DOM 模板時是十分必要的,
由於在 <ul>
元素內只有 <li>
元素會被看做有效內容。這樣作實現的效果與 <todo-item>
相同,
可是能夠避開一些潛在的瀏覽器解析錯誤。查看 DOM 模板解析說明 來了解更多信息。
Vue.component('todo-item', { |
4.事件綁定與監聽
當模板渲染完成以後,就能夠進行事件的綁定與監聽了。
Vue.js提供了v-on指令用來監聽DOM事件,一般在模板內直接使用,而不像傳統方式在js中獲取DOM元素,而後綁定事件。
<button v-on:click="say">say</button>
能夠用 v-on
指令監聽 DOM 事件,並在觸發時運行一些 JavaScript 代碼。
示例:
<div id="example-1"> |
var example1 = new Vue({ |
結果:
The button above has been clicked 0 times.
然而許多事件處理邏輯會更爲複雜,因此直接把 JavaScript 代碼寫在 v-on
指令中是不可行的。所以 v-on
還能夠接收一個須要調用的方法名稱。
示例:
<div id="example-2"> |
var example2 = new Vue({ |
結果:
除了直接綁定到一個方法,也能夠在內聯 JavaScript 語句中調用方法:
<div id="example-3"> |
new Vue({ |
結果:
有時也須要在內聯語句處理器中訪問原始的 DOM 事件。能夠用特殊變量 $event
把它傳入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)"> |
// ... |
在事件處理程序中調用 event.preventDefault()
或 event.stopPropagation()
是很是常見的需求。
儘管咱們能夠在方法中輕鬆實現這點,但更好的方式是:方法只有純粹的數據邏輯,而不是去處理 DOM 事件細節。
爲了解決這個問題,Vue.js 爲 v-on
提供了事件修飾符。以前提過,修飾符是由點開頭的指令後綴來表示的。
.stop
.prevent
.capture
.self
.once
<!-- 阻止單擊事件繼續傳播 --> |
使用修飾符時,順序很重要;相應的代碼會以一樣的順序產生。所以,用 v-on:click.prevent.self
會阻止全部的點擊,而 v-on:click.self.prevent
只會阻止對元素自身的點擊。
2.1.4 新增
<!-- 點擊事件將只會觸發一次 --> |
不像其它只能對原生的 DOM 事件起做用的修飾符,.once
修飾符還能被用到自定義的組件事件上。若是你尚未閱讀關於組件的文檔,如今大可沒必要擔憂。
2.3.0 新增
Vue 還對應 addEventListener
中的 passive
選項提供了 .passive
修飾符。
<!-- 滾動事件的默認行爲 (即滾動行爲) 將會當即觸發 --> |
這個 .passive
修飾符尤爲可以提高移動端的性能。
不要把 .passive
和 .prevent
一塊兒使用,由於 .prevent
將會被忽略,同時瀏覽器可能會向你展現一個警告。
請記住,.passive
會告訴瀏覽器你不想阻止事件的默認行爲。
在監聽鍵盤事件時,咱們常常須要檢查常見的鍵值。Vue 容許爲 v-on
在監聽鍵盤事件時添加按鍵修飾符:
<!-- 只有在 `keyCode` 是 13 時調用 `vm.submit()` --> |
記住全部的 keyCode
比較困難,因此 Vue 爲最經常使用的按鍵提供了別名:
<!-- 同上 --> |
所有的按鍵別名:
.enter
.tab
.delete
(捕獲「刪除」和「退格」鍵).esc
.space
.up
.down
.left
.right
能夠經過全局 config.keyCodes
對象自定義按鍵修飾符別名:
// 可使用 `v-on:keyup.f1` |
2.5.0 新增
你也可直接將 KeyboardEvent.key
暴露的任意有效按鍵名轉換爲 kebab-case 來做爲修飾符:
<input @keyup.page-down="onPageDown"> |
在上面的例子中,處理函數僅在 $event.key === 'PageDown'
時被調用。
有一些按鍵 (.esc
以及全部的方向鍵) 在 IE9 中有不一樣的 key
值, 若是你想支持 IE9,它們的內置別名應該是首選。
2.1.0 新增
能夠用以下修飾符來實現僅在按下相應按鍵時才觸發鼠標或鍵盤事件的監聽器。
.ctrl
.alt
.shift
.meta
注意:在 Mac 系統鍵盤上,meta 對應 command 鍵 (⌘)。在 Windows 系統鍵盤 meta 對應 Windows 徽標鍵 (⊞)。在 Sun 操做系統鍵盤上,meta 對應實心寶石鍵 (◆)。在其餘特定鍵盤上,尤爲在 MIT 和 Lisp 機器的鍵盤、以及其後繼產品,好比 Knight 鍵盤、space-cadet 鍵盤,meta 被標記爲「META」。在 Symbolics 鍵盤上,meta 被標記爲「META」或者「Meta」。
例如:
<!-- Alt + C --> |
請注意修飾鍵與常規按鍵不一樣,在和 keyup
事件一塊兒用時,事件觸發時修飾鍵必須處於按下狀態。
換句話說,只有在按住 ctrl
的狀況下釋放其它按鍵,才能觸發 keyup.ctrl
。而單單釋放 ctrl
也不會觸發事件。
若是你想要這樣的行爲,請爲 ctrl
換用 keyCode
:keyup.17
。
.exact
修飾符2.5.0 新增
.exact
修飾符容許你控制由精確的系統修飾符組合觸發的事件。
<!-- 即便 Alt 或 Shift 被一同按下時也會觸發 --> |
2.2.0 新增
.left
.right
.middle
這些修飾符會限制處理函數僅響應特定的鼠標按鈕。
你可能注意到這種事件監聽的方式違背了關注點分離 (separation of concern) 這個長期以來的優良傳統。
但沒必要擔憂,由於全部的 Vue.js 事件處理方法和表達式都嚴格綁定在當前視圖的 ViewModel 上,它不會致使任何維護上的困難。
實際上,使用 v-on
有幾個好處:
掃一眼 HTML 模板便能輕鬆定位在 JavaScript 代碼裏對應的方法。
由於你無須在 JavaScript 裏手動綁定事件,你的 ViewModel 代碼能夠是很是純粹的邏輯,和 DOM 徹底解耦,更易於測試。
當一個 ViewModel 被銷燬時,全部的事件處理器都會自動被刪除。你無須擔憂如何本身清理它們。
4.3與傳統事件綁定的區別
5.vue.extend()