vue文檔以及api閱讀整理
更新時間2019-12-20
雖然vue3.0馬上要發(fā)布了, 但是我認(rèn)為許多核心api還是不會變的,趁著最近有空,再次精讀文檔,每次閱讀都有很大的收獲.
此次精讀主要分析整理一些個人比較薄弱的功能模塊
加上自己日常使用的一些心得, 以更加通俗的語言描述出來
對于基礎(chǔ)性的東西文檔中都講的很清楚
基本指令
- v-text 輸出渲染后的值
- v-html 輸出解析HTML元素后的值
- v-if 條件判斷
- v-else-if
- v-else
- v-for 循環(huán)
- v-model 表單雙向數(shù)據(jù)綁定
- v-show 控制元素顯示與隱藏
- v-bind 綁定元素的屬性和style
- v-on 綁定事件
- v-pre 原樣輸出
- v-clock 渲染完之后才顯示琼掠,防止將{{message}}類似的輸出到頁面
- v-once 只渲染一次
生命周期
- beforeCreate
- 創(chuàng)建前) 在數(shù)據(jù)觀測和初始化事件還未開始
- created
- (創(chuàng)建后) 完成數(shù)據(jù)觀測,屬性和方法的運(yùn)算瘟忱,初始化事件燎窘,$屬性還沒有顯示出來(載入前)在掛載開始之前被調(diào)用矾瘾,相關(guān)的函數(shù)首次被調(diào)用姥闭。實例已完成以下的配置:編譯模板,把里面的數(shù)據(jù)和模板生成贪染。注意此時還沒有掛載到頁面上缓呛。(載入后)在被新創(chuàng)建的el屬性還沒有顯示出來
- beforeMount
- (載入前) 在掛載開始之前被調(diào)用,相關(guān)的render函數(shù)首次被調(diào)用杭隙。實例已完成以下的配置:編譯模板哟绊,把data里面的數(shù)據(jù)和模板生成html。注意此時還沒有掛載html到頁面上痰憎。此時打印this.$el 輸出的是節(jié)點
- mounted
- (載入后) 在el 被新創(chuàng)建的vm . el 輸出的是節(jié)點內(nèi)掛載的DOM元素
- beforeUpdate
- (更新前) 在數(shù)據(jù)更新之前調(diào)用蜗细,發(fā)生在虛擬DOM重新渲染和打補(bǔ)丁之前裆操∨辏可以在該鉤子中進(jìn)一步地更改狀態(tài),不會觸發(fā)附加的重渲染過程踪区。數(shù)據(jù)改變,但是還沒有渲染的時候
- updated
- (更新后) 在由于數(shù)據(jù)更改導(dǎo)致的虛擬DOM重新渲染和打補(bǔ)丁之后調(diào)用昆烁。調(diào)用時,組件DOM已經(jīng)更新朽缴,所以可以執(zhí)行依賴于DOM的操作善玫。然而在大多數(shù)情況下,應(yīng)該避免在此期間更改狀態(tài)密强,因為這可能會導(dǎo)致更新無限循環(huán)茅郎。該鉤子在服務(wù)器端渲染期間不被調(diào)用。頁面渲染之后
- activated
- keep-alive 組件激活時調(diào)用或渤。
- deactivated
- keep-alive 組件停用時調(diào)用.
- beforeDestroy
- (銷毀前) 在實例銷毀之前調(diào)用系冗。實例仍然完全可用。
- destroyed
- (銷毀后) 在實例銷毀之后調(diào)用薪鹦。調(diào)用后掌敬,所有的事件監(jiān)聽器會被移除,所有的子實例也會被銷毀池磁。該鉤子在服務(wù)器端渲染期間不被調(diào)用奔害。
- errorCaptured
計算屬性
計算屬性的緩存 vs 方法
在許多情況下,計算屬性和方法都能達(dá)到同樣的效果,我們可以將同一函數(shù)定義為一個方法而不是一個計算屬性。兩種方式的最終結(jié)果確實是完全相同的地熄。然而华临,不同的是計算屬性是基于它們的依賴進(jìn)行緩存的。只在相關(guān)依賴發(fā)生改變時它們才會重新求值端考。這就意味著只要 依賴條件 還沒有發(fā)生改變雅潭,多次訪問 函數(shù) 計算屬性會立即返回之前的計算結(jié)果,而不必再次執(zhí)行函數(shù)却特。
計算屬性和方法對比, 計算屬性有緩存, 依賴不變不更新, 而方法每次都要執(zhí)行
計算屬性和watch對比, 可以簡單理解 計算屬性為多個參數(shù)影響一個, watch是一個變化,可以去操作多個
計算屬性的 setter
- 所有 getter 和 setter 的 this 上下文自動地綁定為 Vue 實例扶供。
- 計算屬性默認(rèn)只顯示getter,當(dāng)你需要的時候也可以提供一個setter
- 注意如果你為一個計算屬性使用了箭頭函數(shù),則 this 不會指向這個組件的實例裂明,不過你仍然可以將其實例作為函數(shù)的第一個參數(shù)來訪問椿浓。
// ...
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
vm.fullName = 'jack ma'
<!-- 此時會觸發(fā)set -->
watch 屬性
watch: {
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
# 方法名
b: 'someMethod',
# 深度 watcher
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
},
# 該回調(diào)將會在偵聽開始之后被立即調(diào)用
d: {
handler: function (val, oldVal) { /* ... */ },
immediate: true
},
e: [
function handle1 (val, oldVal) { /* ... */ },
function handle2 (val, oldVal) { /* ... */ }
],
# watch vm.e.f's value: {g: 5}
'e.f': function (val, oldVal) { /* ... */ }
}
條件渲染
- v-if
- v-else // 必須緊跟在帶 v-if 或者 v-else-if 的元素的后面
- v-if-else // 必須搭配v-if使用并且必須緊跟在帶 v-if 或者 v-else-if 的元素之后
v-if 會盡可能的高效地復(fù)用元素,所以v-if兩個代碼塊有相同元素的時候,很可能,會被復(fù)用,解決辦法:只需添加一個具有唯一值的 key 屬性即可
v-if vs v-show
v-if 是“真正”的條件渲染,因為它會確保在切換過程中條件塊內(nèi)的事件監(jiān)聽器和子組件適當(dāng)?shù)乇讳N毀和重建闽晦。
v-if 也是惰性的:如果在初始渲染時條件為假扳碍,則什么也不做——直到條件第一次變?yōu)檎鏁r,才會開始渲染條件塊尼荆。
相比之下左腔,v-show 就簡單得多——不管初始條件是什么,元素總是會被渲染捅儒,并且只是簡單地基于 CSS 進(jìn)行切換液样。
一般來說振亮,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷鞭莽。因此坊秸,如果需要非常頻繁地切換,則使用 v-show 較好澎怒;如果在運(yùn)行時條件很少改變褒搔,則使用 v-if 較好。
列表渲染
- 可以渲染數(shù)組,對象,數(shù)字,字符串
<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, key, index) in object"></div>
- key
- 和元素復(fù)用性能有關(guān)喷面,有相同父元素的子元素必須有獨(dú)特的 key星瘾,一般可以用id
顯示過濾后的數(shù)據(jù)
- items 可以是computed屬性
- items 可以是methods方法
數(shù)組的更新
修改數(shù)組中的數(shù)據(jù),但是頁面渲染不會響應(yīng)式的更新可以通過以下三種方式
- 變異方法
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reserve()
- 改變引用 | 重新賦值 | 替換數(shù)組
- 使用新數(shù)組替換舊的數(shù)組
- set方法 (同樣適用于對象的更新)
Vue.set(vm.items, indexOfItem, newValue)
vm.$set(vm.items, indexOfItem, newValue)
對象的屬性的添加刪除
Vue 不能檢測對象屬性的添加或刪除
使用set方法添加響應(yīng)式屬性
動態(tài)組件
- 必須使用 <component> 標(biāo)簽
- 使用is屬性決定要渲染的組件
異步組件
<!-- 處理加載狀態(tài) -->
const AsyncComponent = () => ({
// 需要加載的組件 (應(yīng)該是一個 `Promise` 對象)
component: import('./MyComponent.vue'),
// 異步組件加載時使用的組件
loading: LoadingComponent,
// 加載失敗時使用的組件
error: ErrorComponent,
// 展示加載時組件的延時時間。默認(rèn)值是 200 (毫秒)
delay: 200,
// 如果提供了超時時間且組件加載也超時了惧辈,
// 則使用加載失敗時使用的組件琳状。默認(rèn)值是:`Infinity`
timeout: 3000
})
is屬性的使用
在一些標(biāo)簽對內(nèi)部元素有著嚴(yán)格的限制,這個時候我們想要使用組件就需要is屬性
// 這里就會把tr屬性渲染成對應(yīng)的組件,直接使用組件不被允許
<table>
<tr is="blog-post-row"></tr>
</table>
組件的v-model
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
.sync修飾符
<!-- 簡化了雙向綁定的寫法, -->
子組件
this.$emit('update:title', newTitle)
父組件
<text-document v-bind:title.sync="doc.title"></text-document>
Prop
傳遞使用了v-bind 所有傳遞的值都為動態(tài)的,例如
<!-- 傳遞的為字符串 -->
<blog-post likes="42"></blog-post>
<!-- 傳遞的為數(shù)字 -->
<blog-post v-bind:likes="42"></blog-post>
- 數(shù)字
- 字符串
- 布爾值
<!-- 包含該 prop 沒有值的情況在內(nèi),都意味著 `true`,即使子組件設(shè)置了default為false盒齿。--> <blog-post is-published></blog-post>
- 對象
- 數(shù)組
! prop 為單向數(shù)據(jù)流,子組件接收后不能直接修改數(shù)據(jù),如果要對數(shù)據(jù)進(jìn)行加工,需要先將接收到的數(shù)據(jù)賦值給data中自定義的參數(shù)
prop驗證
- type 類型檢查
- String
- Number
- Boolean
- Array
- Object
- Date
- Function
- Symbol
- 自定義構(gòu)造函數(shù) 詳見文檔
- required 是否必填
- validator:function() 自定義驗證函數(shù)
作用域插槽 2.6 更新
對于作用于插槽的理解:正常的插槽不論具名插槽還是匿名插槽都不帶數(shù)據(jù),只是留出一片區(qū)域讓你自己插入
作用域插槽則是帶有數(shù)據(jù)的,樣式父組件說了算念逞,但內(nèi)容可以顯示子組件插槽綁定的。
<!-- 作用域插槽可以輸具名插槽,要講本身的數(shù)據(jù)或者通過prop接收到的數(shù)據(jù)傳出來 -->
<slot name="up" :data="data"></slot>
<!-- 父組件調(diào)用的時候 -->
v-solt 可以用 # 替換
#data="{userdata}"
<child>
<template v-solt:data="userdata"> # 這里使用 user接收傳過來的data,必須要使用template標(biāo)簽和slot-scope
<div class="tmpl">
<span v-for="item in userdata">{{item}}</span>
</div>
</template>
</child>
依賴注入
個人理解在$root 和$parent 都無法很好的訪問上級組件的時候使用依賴注入
依賴注入
- provide選項允許我們指定我們想要提供給后代組件的數(shù)據(jù)/方法边翁。在這個例子中翎承,就是
provide: function () {
return {
getMap: this.getMap
}
}
- inject 然后在任何后代組件里,我們都可以使用 inject 選項來接收指定的我們想要添加在這個實例上的屬性
inject: ['getMap']
循環(huán)引用
遞歸組件
- 遞歸組件調(diào)用自身的時候只能通過name來調(diào)用,不用在自身引入注冊
- 傳值的時候最好做下判斷如果有值再調(diào)用
組件之間的循環(huán)引用
- 組件互相引用,互為父子,形成悖論.只有組件為全局注冊組件時才會解開悖論
- 解決方案
- 等到生命周期鉤子 beforeCreate 時去注冊它:
- 在本地注冊組件的時候符匾,你可以使用 webpack 的異步 import
動畫&&過渡
- 在 CSS 過渡和動畫中自動應(yīng)用 class
- 可以配合使用第三方 CSS 動畫庫叨咖,如 Animate.css
- 在過渡鉤子函數(shù)中使用 JavaScript 直接操作 DOM
- 可以配合使用第三方 JavaScript 動畫庫,如 Velocity.js
參考去哪兒 5-123
過渡的類名
-
v-enter
- 只存在第一幀
-
v-enter-active
- 第一幀到最后一幀
-
v-enter-to
- 第二幀到最后一幀
-
v-leave
- 只存在第一幀
-
v-leave-active
- 第一幀到最后一幀
-
v-leave-to
- 第二幀到最后一幀
v-enter-active,v-leave-active 都是處于整個流程中,故可以用來監(jiān)視過渡的變化
- v-enter 第一幀設(shè)置以一個屬性,第二幀屬性移除 一般都是從無到有,第一幀設(shè)置無
- v-enter-to 因為第一幀已經(jīng)移除,所以第二幀無需設(shè)置
- v-enter-active 檢測到屬性變化,設(shè)置過渡動效時間
v-leave 離開的第一幀,不設(shè)置
v-leave-to 第二幀設(shè)置為改變后的狀態(tài),并移除了第一幀,狀態(tài)改變
-
v-leave-active 檢測到第二幀的變化 設(shè)置過渡動效時間等
綜上, 一般v-enter,v-leave-to寫在一起 v-enter-active,v-leave-active寫在一起設(shè)置相同的效果
對于這些在過渡中切換的類名來說待讳,如果你使用一個沒有名字的 <transition>芒澜,則 v- 是這些類名的默認(rèn)前綴仰剿。如果你使用了 <transition name="my-transition">创淡,那么 v-enter 會替換為 my-transition-enter。
CSS3動畫
- 直接寫在 v-*-active中即可
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
自定義過渡類名 && animate.css的使用
transtion 的API文檔中有明確的解釋
transition API
animate.css 是 基于@keyfamse的animated動畫
自定義名稱的鉤子函數(shù),通過這些鉤子可以自定義對應(yīng)的class過渡類名
- enter-class
- enter-active-class
- enter-to-class (2.1.8+)
- leave-class
- leave-active-class
- leave-to-class (2.1.8+)
通過自定義過渡類名結(jié)合animate.css使用
- 必須使用自定義過渡類名
- 必須先加 animated 這個類
<transition
name="custom-classes-transition"
appear // 允許首次進(jìn)入加載動畫
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
appear-active-class = "animated tada" // 首次進(jìn)入加載的過渡效果具體
>
<p v-if="show">hello</p>
</transition>
同時使用過渡和動畫
對于一些過渡和動畫同時使用的情況,可以在自定義過渡類名中加入 原始的過渡類名,然后書寫對應(yīng)的效果
<transition
name="fade"
type= "animation | transition " // 如果過渡和動畫的時間不一致,這里可以指定以誰的為準(zhǔn)
appear
enter-active-class="animated tada fade-enter-active" // 這里加入了原始的類,可以自定義
leave-active-class="animated bounceOutRight"
appear-active-class = "animated tada"
>
- 但是南吮,在一些場景中琳彩,你需要給同一個元素同時設(shè)置兩種過渡動效,比如 animation 很快的被觸發(fā)并完成了部凑,而 transition 效果還沒結(jié)束露乏。在這種情況中,你就需要使用 type 特性并設(shè)置 animation 或 transition 來明確聲明你需要 Vue 監(jiān)聽的類型涂邀。
- 你也可以自定義效果執(zhí)行時長
<transition :duration="1000">...</transition> <transition :duration="{ enter: 500, leave: 800 }">...</transition>
JS動畫鉤子 && Velocity.js
文檔講的很詳細(xì)了
JS動畫鉤子
多個組件的過渡
當(dāng)有相同標(biāo)簽名的元素切換時瘟仿,需要通過 key 特性設(shè)置唯一的值來標(biāo)記以讓 Vue 區(qū)分它們,否則 Vue 為了效率只會替換相同標(biāo)簽內(nèi)部的內(nèi)容比勉。即使在技術(shù)上沒有必要劳较,給在 <transition> 組件中的多個元素設(shè)置 key 是一個更好的實踐驹止。
過渡模式
在多個元素或組件切換過度的時候,可以設(shè)置mode 模式來控制顯隱順序
- out-in 先隱藏后進(jìn)入
- in-out 先進(jìn)入后隱藏
動態(tài)組件的過渡
- 通過is屬性控制組件
列表的過渡
- 使用 <transition-group> 標(biāo)簽
- 內(nèi)部元素 總是需要 提供唯一的 key 屬性值观蜗。
- 不同于 <transition>臊恋,它會以一個真實元素呈現(xiàn):默認(rèn)為一個 <span>。你也可以通過 tag 特性更換為其他元素
- 其他和原來一樣
列表的排序過渡
- 實現(xiàn)添加刪除等過程中列表的平滑過渡
- v-move 屬性來實現(xiàn) *-move
列表的交錯過渡
- 通過 data 屬性與 JavaScript 通信 墓捻,就可以實現(xiàn)列表的交錯過渡,文檔講的很清楚
可復(fù)用過渡
- 就是封裝一個過渡組件 結(jié)合slot
動態(tài)過渡
- 通過數(shù)據(jù)驅(qū)動的方式設(shè)置過渡效果,具體看文檔
狀態(tài)過渡
- 這部分比較復(fù)雜,主要還是數(shù)據(jù)驅(qū)動的思想.通過數(shù)據(jù)的改變影響
混入
- 我對混入的理解是,你定義一個一個對象,可以寫vue中的數(shù)據(jù),方法,以及生命周期等,在對應(yīng)的組件如果引入了.那么這個對象中定義的就混合為同一個對象抖仅。兩個對象鍵名沖突時,取組件對象的鍵值對.因為混入對象的鉤子將在組件自身鉤子之前調(diào)用砖第。
- 全局混入要慎用,因為他會影響所有實例
- 關(guān)于自定義合并策略,抱歉沒搞懂 - -
extend
主要用途是組件的繼承和多態(tài)
可以將一個組件擴(kuò)展為Vue的一個子類
const compont = {}
const ComVue = Vue.extend(compont)
new ComVue({
el:"#root",
....
})
可以一個組件繼承另一個組件
const Comp2 = {
extend: compont,
.....
}
自定義指令
因為這個文檔已經(jīng)寫的很清楚了,所以這里寫一下我的理解.當(dāng)內(nèi)置指令 例如 v-if 等無法滿足我們需求的時候,我們可以自定義一些指令以幫助我們實現(xiàn)需求. 具體實現(xiàn)方法看文檔.
// 注冊
Vue.directive('my-directive', {
bind: function () {},
inserted: function () {},
update: function () {},
componentUpdated: function () {},
unbind: function () {}
})
渲染函數(shù) && JSX
參考react就很好理解了, vue3.0開放了渲染函數(shù)
render (createElement) {
return createment (
'com-one',{
ref: 'com'
},[
createElement('span',{
ref: 'span'
},this.value)
]
)
}
插件
插件是一個經(jīng)常用到的地方.主要是一些全局功能
1.使用Vue.use()方法使用插件
2.插件的開發(fā)
# wxpay
export const wxpay = {
install:() => {
Vue.prototype.$wxpay = () => {
# xxxx
}
}
}
# toast.js
var Toast = {};
Toast.install = function (Vue, options) {
Vue.prototype.$msg = 'Hello World';
}
module.exports = Toast;
keep-alive
主要用于組件以及路由的緩存, 用于保留組件狀態(tài)或避免重新渲染
- 參數(shù)
- include
- exclude
- max
- 生命周期
- activated
- deactivated