? ? ? ?emmmmm,蚊惯,之前因?yàn)殚_(kāi)項(xiàng)目來(lái)不及仔細(xì)讀一遍愿卸,只能是用到什么找什么,然而深感對(duì)vue了解的無(wú)力(?д?截型;)趴荸。。還有一個(gè)周開(kāi)新項(xiàng)目宦焦,恩发钝,認(rèn)真看一哈!( ̄▽ ̄)
【本文并沒(méi)有講解全部API波闹,因?yàn)樘嗔嗽秃馈!舔痪?偨Y(jié)了部分我覺(jué)得重要的點(diǎn)加以分析】
傳送門:Vue.js中文API
Vue參考MVVM模式寓调,使用vm (ViewModel 的簡(jiǎn)稱)來(lái)表示Vue實(shí)例
? ? ? ?vue是一個(gè)虛擬DOM的,以數(shù)據(jù)驅(qū)動(dòng)為核心的前端框架锄码。數(shù)據(jù)驅(qū)動(dòng)也可以稱為響應(yīng)式系統(tǒng),當(dāng)屬性的值發(fā)生變化時(shí)晌涕,視圖都會(huì)“及時(shí)響應(yīng)”滋捶,并更新相應(yīng)的新值。
實(shí)例生命周期鉤子函數(shù)
? ? ? ?每個(gè) Vue 實(shí)例在被創(chuàng)建之前余黎,都要經(jīng)過(guò)一系列的初始化過(guò)程重窟,例如,Vue 實(shí)例需要設(shè)置數(shù)據(jù)觀察(set up data observation)惧财、編譯模板(compile the template)巡扇、在 DOM 掛載實(shí)例(mount the instance to the DOM)扭仁,以及在數(shù)據(jù)變化時(shí)更新 DOM(update the DOM when data change)。在這個(gè)過(guò)程中厅翔,Vue 實(shí)例還會(huì)調(diào)用執(zhí)行一些生命周期鉤子函數(shù)乖坠,這樣用戶能夠在特定階段添加自己的代碼。
? ? ? ?(圖可能不是很清晰刀闷,小伙伴們可以參考原圖)
- 對(duì)于數(shù)據(jù)的操作熊泵,比如props、data甸昏、computed的初始化都是在beforeCreate與created之間完成的顽分,所以不了解的時(shí)候很可能會(huì)出現(xiàn)在別的鉤子操作數(shù)據(jù)而產(chǎn)生奇奇怪怪的問(wèn)題。
- 有一點(diǎn)要注意施蜜, 一般情況下vue組件總是會(huì)走完全部的生命周期的卒蘸,即使你在created或者其他早期的生命周期鉤子中使用了路由跳轉(zhuǎn)或者location.herf重定向。
- 一些因生命周期問(wèn)題而導(dǎo)致無(wú)法使頁(yè)面刷新的問(wèn)題有如下解決方案:
①this.nextTick({ })具體使用方法請(qǐng)移步傳送門
②vuex
③setTimeout(code,millisec) 【可以強(qiáng)制推遲頁(yè)面加載xx毫秒翻默,強(qiáng)烈不推薦悬秉,暫緩之計(jì),具體病因還是要具體解決】 - 生命周期鉤子是一個(gè)很強(qiáng)大的功能冰蘑,可以很好地處理掛載以及異步加載相關(guān)的事件和泌,在特定階段執(zhí)行特定的代碼,比如某幾張圖的出現(xiàn)順序祠肥、比如axios請(qǐng)求數(shù)據(jù)來(lái)異步刷新等武氓。
- 注意,任何生命周期鉤子 中 this 上下文都會(huì)指向調(diào)用它的 Vue 實(shí)例仇箱。
關(guān)于生命周期具體理解推薦一篇文章來(lái)自segmentfault
3. 關(guān)于computed和watcher县恕,留個(gè)flag,匯總一下再寫(xiě)
4. 修飾符(modifier)是以 . 表示的特殊后綴剂桥,表明應(yīng)當(dāng)以某種特殊方式綁定指令忠烛。
? ? ? ?關(guān)于修飾符,請(qǐng)移步我的一篇搬運(yùn)文章? Vue修飾符詳解
5. 渲染
? ? ? ?1. 根據(jù)條件進(jìn)行渲染:v-if與v-show
-
v-if與v-show可以對(duì)內(nèi)容進(jìn)行靈活的選擇性加載权逗,是使用比較多的指令美尸。
? ? ? ?其二者的區(qū)別是,v-if是“真實(shí)”的條件渲染斟薇,因?yàn)樗鼤?huì)確保條件塊(conditional block)在切換的過(guò)程中师坎,完整地銷毀(destroy)和重新創(chuàng)建(re-create)條件塊內(nèi)的事件監(jiān)聽(tīng)器和子組件。且v-if是惰性的(lazy)堪滨,如果在初始渲染時(shí)條件為 false胯陋,它不會(huì)執(zhí)行任何操作。直到在條件第一次變?yōu)?true 時(shí),才開(kāi)始渲染條件塊遏乔。
? ? ? ?相比之下义矛,v-show 要簡(jiǎn)單得多 - 不管初始條件如何,元素始終渲染盟萨,并且只是基于 CSS 的切換凉翻。
? ? ? ?通常來(lái)說(shuō),v-if 在切換時(shí)有更高的性能開(kāi)銷鸯旁,而 v-show 在初始渲染時(shí)有更高的性能開(kāi)銷噪矛。因此,如果需要頻繁切換铺罢,推薦使用 v-show艇挨,如果條件在運(yùn)行時(shí)改變的可能性較少,推薦使用 v-if韭赘。
? ? ? ?2. 列表渲染:v-for
- 在 v-for 代碼塊中缩滨,我們可以完全地訪問(wèn)父級(jí)作用域下的屬性。v-for 還支持可選的第二個(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' }
]
}
})
結(jié)果:- 也可以使用 v-for 來(lái)遍歷對(duì)象的屬性脉漏,接著提供第二個(gè)參數(shù),作為對(duì)象的鍵名(key)袖牙,然后第三個(gè)參數(shù)作為索引(index):
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</div>
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
結(jié)果:注意侧巨,在遍歷一個(gè)對(duì)象時(shí),是按照 Object.keys() 得出 key 的枚舉順序來(lái)遍歷鞭达,無(wú)法保證在所有 JavaScript 引擎實(shí)現(xiàn)中完全一致司忱。
- 關(guān)于key,下列是API的原文
<div v-for="item in items" :key="item.id">
<!-- content -->
</div>
推薦在使用 v-for 時(shí)畴蹭,盡可能提供一個(gè) key坦仍,除非迭代的 DOM 內(nèi)容足夠簡(jiǎn)單,
或者你是故意依賴于默認(rèn)行為來(lái)獲得性能提升叨襟。
由于這是 Vue 識(shí)別節(jié)點(diǎn)的通用機(jī)制繁扎,因此 key 并不是僅限于與 v-for 關(guān)聯(lián),
我們將在之后的指南中看到糊闽,key 還可以其他場(chǎng)景使用梳玫。
因?yàn)闆](méi)有用到過(guò)所以不是很理解,給個(gè)flag后續(xù)了解墓怀。
-
帶有v-if的v-for
當(dāng)它們都處于同一節(jié)點(diǎn)時(shí)汽纠,v-for 的優(yōu)先級(jí)高于 v-if。這意味著傀履,v-if 將分別在循環(huán)中的每次迭代上運(yùn)行。當(dāng)你只想將某些項(xiàng)渲染為節(jié)點(diǎn)時(shí),這會(huì)非常有用钓账,如下:
<li v-for="todo in todos" v-if="!todo.isComplete">
{{ todo }}
</li>
-
關(guān)于v-once
用法:<span v-once></span>
在API中給出的建議是性能優(yōu)化碴犬,事實(shí)也確實(shí)如此,不過(guò)需要注意的是梆暮,用v-once
指令修飾的html內(nèi)容在加載的時(shí)候會(huì)且只會(huì)加載一次
? ? ? ?劃重點(diǎn)7!@泊狻偿荷!
? ? ? ?3. 數(shù)組變化檢測(cè)(Array Change Detection)
? ? ? ?Vue 將觀察數(shù)組(observed array)的變化數(shù)組方法(mutation method)包裹起來(lái),以便在調(diào)用這些方法時(shí)唠椭,也能夠觸發(fā)視圖更新跳纳。這些包裹的方法如下:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
由于 JavaScript 的限制,Vue 無(wú)法檢測(cè)到以下數(shù)組變動(dòng):
- 當(dāng)你使用索引直接設(shè)置一項(xiàng)時(shí)贪嫂,例如
vm.items[indexOfItem] = newValue
- 當(dāng)你修改數(shù)組長(zhǎng)度時(shí)寺庄,例如
vm.items.length = newLength
? ? ? ?所以,使用Vue.set(example1.items, indexOfItem, newValue)
來(lái)解決第一個(gè)問(wèn)題力崇,
使用example1.items.splice(indexOfItem, 1, newValue)
來(lái)解決第一和第二個(gè)問(wèn)題斗塘。
這兩種方法可以通過(guò)響應(yīng)式系統(tǒng)觸發(fā)狀態(tài)更新。
? ? ? ?4. 對(duì)象變化檢測(cè)(Array Change Detection)
受現(xiàn)代 Javascript 的限制亮靴, Vue 無(wú)法檢測(cè)到對(duì)象屬性的添加或刪除:
var vm = new Vue({ data: { a: 1 } }) // `vm.a` 是響應(yīng)的 vm.b = 2 // `vm.b` 不是響應(yīng)的
? ? ? ?Vue 不允許在已經(jīng)創(chuàng)建的實(shí)例上馍盟,動(dòng)態(tài)地添加新的根級(jí)響應(yīng)式屬性(root-level reactive property)。然而茧吊,可以使用 Vue.set(object, key, value) 方法贞岭,將響應(yīng)式屬性添加到嵌套的對(duì)象上。例如:
var vm = new Vue({ data: { userProfile: { name: 'Anika' } }})
? ? ? ?可以向嵌套的 userProfile 對(duì)象饱狂,添加一個(gè)新的 age 屬性:
? ? ? ?Vue.set(vm.userProfile, 'age', 27)
? ? ? ?還可以使用 vm.$set 實(shí)例方法曹步,這也是全局 Vue.set 方法的別名:
? ? ? ?vm.$set(this.userProfile, 'age', 27)
? ? ? ?這是剛接觸Vue的時(shí)候踩到過(guò)的一個(gè)大坑,現(xiàn)在想起來(lái)還頭皮發(fā)麻
∑(?Д?ノ)ノ
6. DOM 模板解析
當(dāng)時(shí)用DOM模板時(shí)休讳,會(huì)受到一些來(lái)源于HTML的限制讲婚,比如,這種寫(xiě)法是報(bào)錯(cuò)的:
<table>
<!--my-row是自定義模板-->
<my-row>...</my-row>
</table>
解決方案:
<table>
<tr is="my-row"></tr>
</table>
is
屬性請(qǐng)自行百度俊柔。
敲黑板
在使用以下字符串模板之一的場(chǎng)景中筹麸,這些限制將不再適用:
- <script type="text/x-template">
- JavaScript 內(nèi)聯(lián)模板字符串
- .vue 組件
所以,用.vue吧雏婶,畢竟用的就是vue框架233333_(:з」∠)_
7. 組件復(fù)用
組件(component)是 Vue 最強(qiáng)大的功能之一物赶。組件可以幫助你擴(kuò)展基本的 HTML 元素,以封裝可重用代碼留晚。
在編寫(xiě)組件時(shí)酵紫,記住是否要復(fù)用組件有好處。一次性組件跟其它組件緊密耦合沒(méi)關(guān)系,但是可復(fù)用組件應(yīng)當(dāng)定義一個(gè)清晰的公開(kāi)接口奖地。
Vue 組件的 API 來(lái)自三部分 - props, events 和 slots :
- Props 允許外部環(huán)境傳遞數(shù)據(jù)給組件
- Events 允許組件對(duì)外部環(huán)境產(chǎn)生副作用(side effects)
- Slots 允許外部環(huán)境將額外的內(nèi)容組合在組件中橄唬。
8. 組件的組合與通信
組件,意味著組合在一起使用的元件参歹,多數(shù)場(chǎng)景是父子關(guān)系:組件 A 可以在自己的模板中使用組件 B仰楚。這就必然的需要彼此相互通信:父組件可能會(huì)向下傳遞數(shù)組給子組件,然后子組件也可能會(huì)將自身發(fā)生的變化通知到父組件犬庇。然而僧界,重要的是,為了盡可能將父子組件解耦臭挽,需要有一個(gè)定義清晰的接口捂襟。定義清晰的通信方式,可以確保組件可以相對(duì)隔離地組織代碼埋哟,以及合乎邏輯易于推斷笆豁,從而使它們更加易于維護(hù),并且可能更加易于復(fù)用赤赊。
vue的大方面的功能核心就是組件闯狱,正是組件的組合嵌套復(fù)用構(gòu)成了快速且多樣的vue項(xiàng)目生態(tài)圈,而組件通信又是組件中比較重要的知識(shí)點(diǎn)抛计。
-
父向子組件:
- 在子組件中添加props(既可以傳遞數(shù)據(jù)也可以傳遞方法)
常用形式<child :msg = "parentMsg"/>
含有路由出口的使用形式<router-view :propsdata="data"/> - this.$broadcast 調(diào)用子組件方法(子組件在events中寫(xiě)被調(diào)用方法)
- 父組件通過(guò)this.$ref獲得子組件的引用
【$refs 只在組件渲染完成后才填充哄孤,并且它是非響應(yīng)式的。它僅僅作為一個(gè)直接訪問(wèn)子組件的應(yīng)急方案 - 應(yīng)當(dāng)避免在模板或計(jì)算屬性中使用 $refs吹截∈莩拢】 - 使用this.$children()獲得子組件的Vue實(shí)例
- 在子組件中添加props(既可以傳遞數(shù)據(jù)也可以傳遞方法)
-
子向父組件:
- this.$emit (父組件在methods中寫(xiě)被調(diào)用方法,并通過(guò)@event綁定到子組件) 波俄,子組件中通過(guò)這種方法傳遞數(shù)給父組件同時(shí)激活父組件的被調(diào)用方法晨逝。
- this.$dispath (父組件在events中寫(xiě)被調(diào)用方法)
- 在子組件中添加插槽slot,父組件可以向子組件中插入模板 <template/> ,通過(guò)slot-scope獲得子組件返回的值
- 使用this.$parent獲得父組件Vue實(shí)例 (this.$root獲得根組件的Vue實(shí)例)
一點(diǎn)補(bǔ)充:在某些場(chǎng)景中懦铺,我們可能需要對(duì)一個(gè) prop 進(jìn)行「雙向綁定」 - 事實(shí)上捉貌,這個(gè)功能在 Vue 1.x 中已經(jīng)由
.sync
修飾符實(shí)現(xiàn)。但是在2.0中移除冬念,在2.3.0+中以語(yǔ)法糖的形式再次加入趁窃。雖然用的不多,如果想了解請(qǐng)移步API急前。
- 通過(guò)bus.js或者自身的vue實(shí)例來(lái)進(jìn)行不同組件之間的數(shù)據(jù)傳遞
- 通過(guò)new一個(gè)Vue對(duì)象作為通信的橋梁(bus.$emit() => bus.$on())
- 自身的vue實(shí)例(this.$emit() => this.$on())
- Flux以及Vuex(全局單例模式)同時(shí)也可用于解決不同組件之間的通信問(wèn)題(解決了繁雜事件訂閱和廣播)
- 路由傳參
這里要注意醒陆,第一種方式是無(wú)法傳參的,要傳參必須通過(guò)第二種方式裆针,即以name
的形式而不能以路徑的形式刨摩。所以在路由中的定義如下第三張圖寺晌。
關(guān)于slot,與props相似码邻,簡(jiǎn)單來(lái)說(shuō)就是props把數(shù)據(jù)扔到子組件中折剃,slot把html扔到子組件中另假。關(guān)于slot留個(gè)flag后續(xù)寫(xiě)個(gè)專欄具體補(bǔ)充像屋。。边篮。
請(qǐng)注意己莺,props是單向數(shù)據(jù)流,按照自上而下單向流動(dòng)方式構(gòu)成
9. 動(dòng)態(tài)組件
- 簡(jiǎn)單來(lái)說(shuō)戈轿,與v-bind動(dòng)態(tài)選擇css一個(gè)樣子凌受,根據(jù)父組件給的變量決定顯示哪個(gè)組件,或者都不顯示思杯。
- 使用方式:
<component v-bind:is="組件名"></component>
- 有一點(diǎn)需要注意胜蛉,像v-if一樣,動(dòng)態(tài)加載組件是需要重渲染的色乾,所以如果想避免重新渲染可以添加keep-alive屬性來(lái)保持已渲染的組件不被移除誊册。
<component v-bind:is="組件名" keep-alive></component>
- activate延遲加載
activate是和data等屬性平級(jí)的一個(gè)屬性,形式是一個(gè)函數(shù)暖璧,函數(shù)里默認(rèn)有一個(gè)參數(shù)案怯,而這個(gè)參數(shù)是一個(gè)函數(shù)翼抠。
如下實(shí)例:
data(){
return{
//...
}
},
activate (done) { //執(zhí)行這個(gè)參數(shù)時(shí)茵休,才會(huì)切換組件
var self = this;
//
axios.get("/test", function (data) {
self.hello = data;
done(); //ajax執(zhí)行成功,切換組件
})
}
注意:
【1】只有在第一次渲染組件時(shí)址否,才會(huì)執(zhí)行activate局蚀,且該函數(shù)只會(huì)執(zhí)行一次(在第一次組件出現(xiàn)的時(shí)候延遲組件出現(xiàn))
【2】沒(méi)有keep-alive時(shí)麦锯,每次切換組件出現(xiàn)都是重新渲染(因?yàn)橹半[藏時(shí)執(zhí)行了destroy過(guò)程),因此會(huì)執(zhí)行activate方法琅绅。
10. 組件雜項(xiàng)
以下全部有待補(bǔ)充扶欣,慣例,flaggggggggggggg
- 異步組件/代碼分離
應(yīng)用做大了以后可以進(jìn)行性能優(yōu)化奉件,后續(xù)詳細(xì)補(bǔ)充 - 命名規(guī)范
- 組件之間的循環(huán)引用
- 組件庫(kù)
- 其他
11. 過(guò)渡&動(dòng)畫(huà)
概述
過(guò)渡和動(dòng)畫(huà)可以對(duì)頁(yè)面內(nèi)容以及用戶體驗(yàn)做一些良好的提升宵蛀,避免生硬的切換效果帶來(lái)的挫頓感。個(gè)人看法:如果不考慮模塊化發(fā)布或者工程量不是很大县貌,在系統(tǒng)功能完善之后進(jìn)行過(guò)度動(dòng)畫(huà)的添加可以對(duì)頁(yè)面逼格進(jìn)行大幅提升~
從頁(yè)面中添加(顯示)术陶、移除(隱藏)或者更新一些成員的時(shí)候,Vue提供了多種的過(guò)渡動(dòng)畫(huà)來(lái)避免生硬的元素轉(zhuǎn)變煤痕。包括以下工具:
- 在 CSS 過(guò)渡和動(dòng)畫(huà)中自動(dòng)處理 class
- 可以配合使用第三方 CSS 動(dòng)畫(huà)庫(kù)梧宫,如 Animate.css
- 在過(guò)渡鉤子函數(shù)中使用 JavaScript 直接操作 DOM
- 可以配合使用第三方 JavaScript 動(dòng)畫(huà)庫(kù)接谨,如 Velocity.js
單元素/組件的過(guò)渡
Vue提供了transition
外層包裹容器組件(wrapper component),可以給下列情形中的任何元素和組件添加進(jìn)入/離開(kāi)(enter/leave)過(guò)渡:
- 條件渲染(使用 v-if)
- 條件展示(使用 v-show)
- 動(dòng)態(tài)組件
- 組件根節(jié)點(diǎn)
一個(gè)demo:
<template>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
</template>
<script>
new Vue({
el: '#demo',
data: {
show: true
}
})
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active 在低于版本 2.1.8 中 */ {
opacity: 0;
}
</style>