前言
接觸 Vue 也有一段時(shí)間了敲长,很多時(shí)候在項(xiàng)目里面會用技俐,但是由于對整個(gè) Vue 的了解比較片面鸣驱,讓我不得不一次又一次地含淚填坑昼牛。不過真是這樣的經(jīng)歷术瓮,也讓我對 Vue 有了很多新的認(rèn)識。
為了深入地學(xué)習(xí) Vue 2.0贰健,就決定寫一個(gè)系列的學(xué)習(xí)筆記胞四,希望在記錄自己走過的路的同時(shí),也能和一起學(xué)的伙伴互相交流伶椿。所以辜伟,也希望看完博客的小伙伴,如果發(fā)現(xiàn)我的什么錯(cuò)誤或者遺漏脊另,也希望及時(shí)地提出來导狡。
關(guān)于 Vue 2.0 的學(xué)習(xí)筆記是一個(gè)系列的集合,包括 Vue 基礎(chǔ)學(xué)習(xí)偎痛、高級組件學(xué)習(xí)旱捧、插件開發(fā)和實(shí)際應(yīng)用,所涵蓋的知識點(diǎn)和技能點(diǎn)也是方方面面踩麦,本文主要針對 Vue 2.0 的常用方法進(jìn)行了總結(jié)枚赡,不包括 Vue 是啥東西?怎么安裝靖榕?這個(gè) Vue 官網(wǎng) 已經(jīng)說的很詳細(xì)了标锄,可以根據(jù)它的教程一步一步來。
放個(gè) Vue 2.0 學(xué)習(xí)筆記其它部分的傳送門(我會堅(jiān)持都寫完的 TAT):
好的茁计,我們開始吧料皇!
1. 生命周期
每個(gè) Vue 實(shí)例在被創(chuàng)建之前都要經(jīng)過一系列的初始化過程,在這個(gè)過程中星压,實(shí)例也會調(diào)用一些生命周期鉤子 践剂,這就給我們提供了執(zhí)行自定義邏輯的機(jī)會。
那么怎么使用這些鉤子呢娜膘?我們先看一個(gè) Vue 實(shí)例的生命周期圖:
如上圖所示逊脯,Vue 的生命周期一共有Create
、Mount
竣贪、Update
以及Destroy
四個(gè)步驟军洼。而 Vue.js 也提供了八個(gè)鉤子函數(shù)給我們自定義邏輯:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
從字面上來解釋就分別是創(chuàng)建前后巩螃、掛載前后、更新前后以及銷毀前后匕争。
注意:Mount 比較簡單的理解就是 Vue 上的
el
替代了 DOM 元素避乏。
我們再通過一個(gè)例子來說明一下:
<template>
<div id="demo1">{{data}}</div>
</template>
<script>
export default {
data() {
return {
name: 'demo1',
a: '999',
data: 'this is data'
}
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
console.log('mounted')
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeDestroy() {
console.log('beforeDestroy')
},
destroyed() {
console.log('destroyed')
},
watch: {
a: function (val, oldVal) {
console.log(`new: ${val}, old: ${oldVal}`)
}
}
}
</script>
我們打開控制臺就會發(fā)現(xiàn),初次加載時(shí)會觸發(fā)Create
和Mount
的生命周期鉤子:
在控制臺中修改 data 中的值甘桑,以及調(diào)用$destroy()
方法拍皮,分別會觸發(fā)Update
和Destroy
的生命周期鉤子:
另外值得一提的是,根據(jù)官網(wǎng)給出的描述:
“每個(gè) Vue 實(shí)例都會代理其 data 對象里的所有屬性跑杭∶保”
通俗一點(diǎn)說就是,data 對象是引用類型德谅,其值是該對象的地址爹橱,所以你改變 data 中的值之后,Vue 實(shí)例中的值也會跟著改變女阀,反過來也是同理宅荤。不過有一點(diǎn)在寫 SPA 的時(shí)候可能不會注意到的是,把一個(gè)對象賦值給 Vue 實(shí)例以后浸策,再給該對象增加屬性冯键,新屬性并不會被原本的 Vue 實(shí)例所引用。例如:
// html
<div id="demo2"></div>
// js
const demoData = {
name: 'demo2',
a: '999',
data: 'this is data'
}
const demo = new Vue({
el: '#demo2',
data: demoData
})
demoData.b = '998'
這樣并不能把新屬性添加到實(shí)例里面庸汗。
把話題撤回來惫确,使用了$destroy()
方法就會觸發(fā) Destroy 的生命周期鉤子,會拆解監(jiān)控蚯舱,也就是解除雙向綁定改化,值得變化不會再引起 DOM 的變化:
如上圖所示,修改了 data 之后枉昏,DOM 上的值依舊沒有發(fā)生變化陈肛。
2. 計(jì)算屬性
計(jì)算屬性被混入到 Vue 實(shí)例中,所有 getter 和 setter 的 this 上下文自動地綁定為 Vue 實(shí)例兄裂。
注意:不應(yīng)該使用箭頭函數(shù)來定義計(jì)算屬性函數(shù) (例如
aDouble: () => this.a * 2
)句旱。理由是箭頭函數(shù)綁定了父級作用域的上下文,所以 this 將不會按照期望指向 Vue 實(shí)例晰奖,this.a
將是 undefined谈撒。
先看 demo 的以下代碼:
<template>
<div id="demo3">
<p>{{fullName}}</p>
<p>{{getFullName()}}</p>
</div>
</template>
<script>
export default {
data() {
return {
firstName: 'Larry',
lastName: 'Xiao'
}
},
methods: {
getFullName() {
console.log('method exec')
return `${this.firstName} ${this.lastName}`
}
},
computed: {
fullName: {
get() {
return `${this.firstName} ${this.lastName}`
},
set(newVal) {
let names = newVal.split(' ')
this.firstName = names[0]
this.lastName = names[names.length-1]
}
}
},
watch: {
a: function (val, oldVal) {
console.log('watch exec')
alert('firstName has changed!')
}
}
}
</script>
可以看到的是,在 computed 中的fullName
和 methods 中的getFullName()
效果是一樣的匾南。根據(jù)文檔上的說法啃匿,計(jì)算屬性是使用計(jì)算緩存的,當(dāng)計(jì)算屬性的依賴項(xiàng)發(fā)生變化時(shí),計(jì)算屬性才會重新計(jì)算溯乒,其他時(shí)候都是直接返回緩存中的值夹厌,而 method 總是會執(zhí)行函數(shù)。
另外橙数,計(jì)算屬性默認(rèn)是 get 模式尊流,同時(shí)也可以采用 set 模式帅戒。
因此灯帮,計(jì)算屬性在大多數(shù)情況都更合適,當(dāng)不需要緩存的時(shí)候用 method逻住,需要緩存的時(shí)候用計(jì)算屬性 computed钟哥,有時(shí)候需要在數(shù)據(jù)變化時(shí)來響應(yīng)數(shù)據(jù)變化,就需要用到 watch 方法瞎访。
3. Class 綁定
在將v-bind
用于 class 和 style 的時(shí)候腻贰,表達(dá)式的結(jié)果類型除了字符串外,還可以是對象是數(shù)組:
對象的綁定方式很簡單扒秸,使用v-bind:class
就行了播演。
需要注意的有:
-
v-bind:class
可以和普通的 class 屬性共存; -
v-bind:class
賦值的對象除了是 js 的字面量意外伴奥,也可以是 data 中所指向的對象写烤,同時(shí)還能是 computed 計(jì)算屬性中返回的對象。
關(guān)于數(shù)組綁定拾徙,可以把一個(gè)數(shù)組傳遞給v-bind:class洲炊,以應(yīng)用一個(gè)class列表,同時(shí)也可以在數(shù)組中使用對象:v-bind:class="[{active:isActive},selectCss]"
尼啡。當(dāng)然同樣的道理暂衡,也可以使用計(jì)算屬性。
4. 內(nèi)聯(lián)樣式綁定
內(nèi)聯(lián)樣式的綁定和 class 的綁定幾乎沒有區(qū)別崖瞭,同樣也是可以綁定對象和數(shù)組:v-bind:style="{color:'red';fontSize:'30px'}"
狂巢,有一點(diǎn)要注意的是,css 的屬性名除了用駝峰法书聚,還可以用短橫分割法命名:v-bind:style="{color:'blue','font-size':'30px',}"
和v-bind:style="{color:'blue',fontSize:'30px',}"
的效果是一模一樣的唧领。當(dāng)然,把v-bind:style
綁定到一個(gè)樣式對象上是個(gè)更好的做法寺惫。
數(shù)組的用法和 class 的一樣疹吃,最后值得一提的是:當(dāng)v-bind:style
使用需要特定前綴的 css 屬性時(shí),如transform
西雀,會自動添加前綴萨驶。并且在 chrome 瀏覽器下,并沒有加上-webkit-
前綴艇肴。
5. 條件渲染
5.1 v-if
在 Vue 項(xiàng)目里面腔呜,一般在處理?xiàng)l件渲染的時(shí)候叁温,都會使用v-if
來處理,而更為強(qiáng)大的一點(diǎn)在于核畴,還有v-else
和v-else-if
來處理多種條件下的渲染問題膝但。
由于v-if
只是一種標(biāo)簽里的指令,如果需要按條件渲染多個(gè)元素的時(shí)候谤草,就需要用到<template></template>
跟束,把多個(gè)元素放在template
里面,把v-if
指令放到template
上丑孩。
Vue 嘗試盡可能高效的渲染元素冀宴,通常會復(fù)用已有元素而不是從頭開始渲染。這么做除了使 Vue 更快之外還可以得到一些好處温学。就像這樣略贮,當(dāng)允許用戶在不同的登錄方式之間切換:
<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
,會顯示不同的 label 和 plaaceholder仗岖,但是在切換的時(shí)候逃延,input 的內(nèi)容并不會被刪除,兩個(gè)模版因?yàn)槭褂昧讼嗤脑卦簦虼?code><input>會被復(fù)用揽祥,僅僅只是替換了 placeholder。當(dāng)然紧帕,Vue 也提供了一種方式讓你自己決定是否要復(fù)用元素盔然,所要做的就是加一個(gè) key 屬性。
5.2 v-show
另一個(gè)根據(jù)條件渲染元素的指令叫v-show
是嗜,和v-if
的區(qū)別在于v-show
做的僅僅只是切換元素的 css 中的display
屬性愈案。另外v-show
也不支持 template 語法。
5.3 v-if 和 v-show 的區(qū)別:
-
v-if
是真實(shí)的條件渲染鹅搪,因?yàn)樗鼤_保條件塊在切換當(dāng)中適當(dāng)?shù)劁N毀與重建條件塊內(nèi)的事件監(jiān)聽器和子組件站绪。 -
v-if
也是惰性的:如果在初始渲染時(shí)條件為假,則什么也不做丽柿,在條件第一次變?yōu)檎鏁r(shí)才開始局部編譯(編譯會被緩存起來)恢准。
相比之下,v-show
簡單得多:元素始終被編譯并保留甫题,只是簡單地基于 CSS 切換馁筐。一般來說,v-if
有更高的切換消耗坠非,而v-show
有更高的初始渲染消耗敏沉。因此,如果需要頻繁切換使用v-show
較好,如果在運(yùn)行時(shí)條件不大可能改變則使用v-if
較好盟迟。
6. 列表渲染
在 Vue 的列表渲染中秋泳,主要使用v-for="item in items"
的指令來進(jìn)行元素渲染。和條件渲染一樣攒菠,當(dāng)有多個(gè)元素需要被渲染的時(shí)候迫皱,也可以使用<template v-for=""></template>
來渲染。
而v-for
指令除了可以渲染數(shù)組以外辖众,也能渲染對象以及整數(shù)的迭代:
- 在渲染數(shù)組時(shí)卓起,
v-for
還支持可選的第二個(gè)參數(shù)為當(dāng)前項(xiàng)的索引,即v-for="(item,index) in intems"
赵辕; - 而在渲染對象時(shí)既绩,
v-for
支持第二個(gè)可選參數(shù)作為鍵名,第三個(gè)參數(shù)作為索引还惠,v-for="(value,key,index) in items"
; - 進(jìn)行整數(shù)迭代時(shí):
<span v-for="x in 15">{{x}}</span>
私杜。
為了給 Vue 一個(gè)提示蚕键,以便它能跟蹤每個(gè)節(jié)點(diǎn)的身份,從而重用和重新排序現(xiàn)有元素衰粹,我們需要為每項(xiàng)提供一個(gè)唯一的 key 屬性锣光。理想的 key 值是每項(xiàng)都有唯一 id,它的工作方式類似于一個(gè)屬性铝耻,所以你需要用 v-bind 來綁定動態(tài)值:
<div v-for="item in items" :key="item.id">
<!-- :key 是對于 v-bind 的一種簡寫方式 -->
</div>
除了這些,Vue 還包含一組觀察數(shù)組的變異方法频丘,它們也會觸發(fā)視圖的更新:
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
7. 事件處理器
事件處理器可以使用v-on
指令或者縮寫@
來完成事件綁定泡态,比如我們要綁定一個(gè) click 事件:
<template>
<button v-on:click="add">add</button>
<span></span>
</template>
<script>
data() {
return {
count: 0
}
}
methods: {
add() {
this.count ++
}
}
</script>
有時(shí)候需要在v-on
綁定的事件中處理原生 DOM 的事件,則可以使用$event
將它傳入方法:
<template>
<button v-on:click="warn('Form cannot be submitted yet.', $event)">Submit</button>
</template>
<script>
data() {
return {
}
}
methods: {
warn (message, event) {
if (event) {
event.preventDefault()
}
alert(message)
}
}
</script>
之前提到的桐汤,我們需要在方法中除了原生 DOM 事件怔毛,主要也是為了阻止冒泡方法腾降,為了讓我們可以再 method 中專注于業(yè)務(wù)邏輯,Vue 提供了一些事件修飾符:
- stop:阻止事件冒泡;
- prevent:事件觸發(fā)不再重載頁面混卵;
- capture:添加事件監(jiān)聽器時(shí)使用事件捕獲模式窖张;
- self:只有該事件是自己本身(而不包括子元素)時(shí)才會觸發(fā)回調(diào);
- once:只觸發(fā)一次赘淮。
還有一點(diǎn)要注意的是睦霎,事件修飾符是可以串聯(lián)使用的,比如v-on:click.stop.prevent="click"
副女。
在監(jiān)聽鍵盤事件時(shí)碑幅,還需要監(jiān)聽常見的鍵值,Vue 允許v-on
在監(jiān)聽鍵盤事件時(shí)恤批,添加特殊的鍵盤修飾符裹赴,基本的鍵盤修飾符有:
- .enter
- .tab
- .delete
- .esc
- .space
- .up
- .down
- .left
- .right
還有組合按鍵的修飾符:
- .ctrl
- .shift
- . alt
- .meta(window 系統(tǒng)下是 window 鍵,mac 下是 command 鍵)
8. 表單控件綁定
所謂的表單控件其實(shí)就是使用v-mode
l指令放在<input>
延都、<textarea>
和<select>
這些控件上實(shí)現(xiàn)雙向綁定懊昨。如果是多選,v-model
綁定的對象一定要是個(gè)數(shù)組嫉你,同時(shí)可以通過v-bind
來為 “表單控件” 設(shè)置 value 值躏惋。
并且,還可以在v-model
中使用修飾符來進(jìn)行一些常用操作:
- .lazy:在默認(rèn)情況下距误,
v-model
在 input 事件中同步輸入框的值與數(shù)據(jù),但你可以添加一個(gè)修飾符 lazy 趁俊,從而轉(zhuǎn)變?yōu)樵谑录型剑?/li>
<input v-model.lazy="msg">
- .number:如果想自動將用戶的輸入值轉(zhuǎn)為 Number 類型(如果原值的轉(zhuǎn)換結(jié)果為 NaN 則返回原值)刑然,可以添加一個(gè)修飾符 number 給
v-model
來處理輸入值:
<input v-model.number="age" type="number">
- .trim:如果要自動過濾用戶輸入的首尾空格泼掠,可以添加 trim 修飾符到
v-model
上過濾輸入:
<input v-model.trim="msg">
總結(jié)
本文大概地過了一遍 Vue 2.0 的基礎(chǔ)知識,也可能還有很多方面不夠詳盡挡逼,希望大佬可以多提建議腻豌。還有一點(diǎn)比較重要的就是,學(xué)習(xí) Vue 2.0 的話乘盖,我個(gè)人還是建議去 Vue 官網(wǎng) 跟著一步一步地敲代碼憔涉,博客只是一個(gè)總結(jié)概括的東西析苫,真正理解還得自己實(shí)踐。
當(dāng)然国旷,也希望這些總結(jié)可以對我自己茫死,以及對剛接觸 Vue 2.0 的小伙伴有些幫助吧!