1. 程式人生 > >[ vue ] 生命週期 & 常見坑

[ vue ] 生命週期 & 常見坑

vue生命週期(重)

image

  1. beforeCreate
  2. created
  3. beforeMount
  4. mounted
  5. beforeUpdate
  6. updated
  7. beforeDestroy
  8. destroyed
------beforeCreate建立前狀態------
 el     : undefined
 data   : undefined
 message: undefined
 ------created建立完畢狀態------
 el     : undefined
 data   : [object Object]   ~~~
 message: Vue的生命週期
 ------beforeMount掛載前狀態------
 el     : [object HTMLDivElement]   ~~~
 <div id=​"app">​…​</div>​
 data   : [object Object]
 message: Vue的生命週期
 ------mounted 掛載結束狀態------
 el     : [object HTMLDivElement]
 <div id=​"app">​…​</div>​
 data   : [object Object]
 message: Vue的生命週期
beforeCreate(例項初始化之後,資料觀測、event/watcher 事件配置之前) ——> 
created(在例項建立完畢後立即被呼叫) ——> 
beforeMount(在掛載開始之前被呼叫) ——> 
mounted ——> 
beforeUpdated(資料更新時呼叫) ——> 
updated (虛擬Dom重新渲染和打補丁之後呼叫)——> 
activated(keep-alive 元件啟用時呼叫) ——> 
deactived(keep-alive 元件停用時呼叫)——> 
beforeDestory(例項銷燬前呼叫)——> 
destoryed (Vue例項後呼叫)

1.在beforeCreate和created鉤子函式之間的生命週期

初始化事件,進行資料的觀測,可以看到在created的時候資料已經和data屬性進行繫結(放在data中的屬性當值發生改變的同時,檢視也會改變)。

2.created鉤子函式和beforeMount間的生命週期

會判斷物件是否有el選項。如果有的話就繼續向下編譯,如果沒有el選項,則停止編譯,也就意味著停止了生命週期,直到在該vue例項上呼叫vm.$mount(el)

vm.$mount(el) //這個el引數就是掛在的dom接點

template引數選項的有無對生命週期的影響。

  1. 如果vue例項物件中有template引數選項,則將其作為模板編譯成render函式。
  2. 如果沒有template選項,則將外部HTML作為模板編譯。
  3. 可以看到template中的模板優先順序要高於outer HTML的優先順序。

render函式選項 > template選項 > outer HTML.

3.beforeMount和mounted 鉤子函式間的生命週期

vue例項物件新增$el成員,並且替換掉掛在的DOM元素。因為在之前console中列印的結果可以看到beforeMount之前el上還是undefined。

4.mounted

在mounted之前h1中還是通過{{message}}進行佔位的,因為此時還有掛在到頁面上,還是JavaScript中的虛擬DOM形式存在的。在mounted之後可以看到h1中的內容發生了變化

5.beforeUpdate鉤子函式和updated鉤子函式間的生命週期

當vue發現data中的資料發生了改變,會觸發對應元件的重新渲染,先後呼叫beforeUpdate和updated鉤子函式。

6.beforeDestroy和destroyed鉤子函式間的生命週期

beforeDestroy鉤子函式在例項銷燬之前呼叫。在這一步,例項仍然完全可用。 destroyed鉤子函式在Vue 例項銷燬後呼叫。呼叫後,Vue 例項指示的所有東西都會解繫結,所有的事件監聽器會被移除,所有的子例項也會被銷燬。

Vue的相關指令

vue常用指令: v-for、v-bind(縮寫形式:prop)、v-on(縮寫形式@click=’sss')、v-if/v-else/v-else-if、v-model、v-once、v-html、v-show...
vue自定義元件:Vue.component(‘componentName',{ props:[‘p1’,’p2’], template: ‘<li>{{ p1 }}</li>' })
vue常用例項方法和屬性: data/$data、methods/$methods、$el、computed(計算屬性)、$watch、$set、$event、$emit...
如果需要更新的屬性需要快取,則使用計算屬性的方式,否則可以使用methods裡的方法來更新屬性(methods裡的方法每次重新渲染都會執行)
計算屬性預設提供了getter,你還可以給它設定setter
當你資料變化是非同步或者開銷較大時,可以使用watch偵聽器來響應資料的變化
v-bind:class的值可以是一個物件,可實現類似react中classnames模組的功能
自定義元件上的class會被渲染拼接到template的根節點的class屬性上(自定義元件上可使用v-bind:class來做class的判斷顯示邏輯)
v-bind:style可以用來繫結內聯樣式,這個內聯樣式的值可以由一個物件來定義(類似css in js的模式),且可以被定義為陣列(多個樣式物件)
v-bind:style可以使用多重值的形式:<div :style=“display:[‘-webkit-box’,’-ms-flexbox’, ‘flex']"></div>
v-if/v-else/v-else-if的時候,可以用key來管理可複用的元素
v-if是’真正’的渲染,它會確保在切換條件過程中條件塊內的元素的事件監聽器和子元件適時的銷燬和重建
v-if是惰性的,初始為假,什麼也不做,直到為真的時候才渲染元素
v-show總是渲染元素,只是簡單的進行切換
v-if的切換開銷大,v-show則是初始渲染開銷大,頻繁切換使用v-show,執行時經常改變則使用v-if
v-if和v-for一起使用時,v-for的優先順序更高
v-for可遍歷陣列,第二個引數是索引
v-for可遍歷物件,第二個引數是key,第三個引數是索引
v-for和<template>搭配可減少渲染次數
v-for和自定義元件使用時,需要使用props來傳遞值
儘可能的為遍歷子元素加上key,獲得渲染優化
陣列變異方法:push/pop/unshift/shift/splice/sort/reverse改變原始陣列
陣列非變異方法:filter/concat/slice 不改變原始陣列,總是返回新陣列
Vue不能檢測到陣列索引賦值(使用vm.$set解決)和修改length長度賦值(使用splice解決)的情況
Vue不能檢測物件屬性的新增和刪除(使用vm.$set或Object.assign)
is=“todo-item”這種屬性的寫法比較適合DOM模板
事件修飾符,它們可串聯使用:.stop、.prevent、.capture、.self、.once、.passive(尤其適合移動端)
.passive不用同時和.prevent使用,後者會被忽略
按鍵修飾符: .enter、.tab、.delete、.esc、.space、.up、.down、.left、.right
系統按鍵修飾符:.ctrl、.alt、.shift、.meta(⌘|⊞|◆)、.exact(允許精確控制系統修飾符組合鍵觸發)
滑鼠修飾符: .left、.right、.middle
v-model會忽略表單元素的value、checked、selected,僅僅使用例項中的資料作為資料來源
表單事件修飾符:.lazy、.number、.trim
元件是可複用的vue例項,具有vue例項大多數屬性和方法
元件可複用,每個元件有獨立的空間
元件上的data必須是一個函式,這樣做避免影響了其他元件
通過Vue.component()全域性註冊的元件可在其被註冊後的任何通過new Vue()建立的例項所使用,包含其元件樹中的所有元件
通過插槽<slot>分發內容(其實就是類似於react的children)
動態元件<component>配合屬性is來實現
解析DOM模板時需要注意下可能會有不生效的情況,需要使用is來傳遞元件

Vue元件

區域性註冊元件在子元件中不可用
全域性註冊的行為必須在根Vue例項建立之前發生
camelCase的屬性可以在元件中使用kebab-case
可以以物件的模式指定每一個props屬性的型別
父級props的更新會向下流動,反之則不行
由於JavaScript物件和陣列是引用傳入的,所以當子元件對props的改變將會影響到父元件
props型別校驗可以是原生構造物件的中的任意一個,也可以自定義檢驗型別,通過instanceof檢查
對於絕大多數特性來說,外部傳入的值會替換掉元件內部設定好的值,如input的type屬性,但有的屬性則是會進行合併,如class
inhertAttrs:false設定不希望根元素繼承特性,可以使用$attrs屬性來設定繼承的目標元素
v-on在設定事件監聽器時,會把事件名全部轉換成小寫,推薦始終使用kebab-case的事件名
v-model可以使用自定義元件中的model屬性自定義
父元件模板的所有東西都會在父級作用域內編譯,子元件的所有內容都會在子元件作用域內編譯
插槽(<slot></slot>)/具名插槽(<slot name=“header"></slot>)/作用域插槽(slot/slot-scope)
<keep-alive>元件可用來快取被切換後隱藏的元件的狀態
$root訪問根例項,$parent訪問父元件例項(不推薦)
父元件訪問子元件,使用$refs屬性來獲取設定了ref屬性的子元件
provide屬性允許我們指定要分享給後代元件使用的方法,然後後代元件使用inject屬性來獲得祖先元件分享的方法(依賴注入)
事件偵聽器($emit派發的事件)

    v-on 指令偵聽
    $on 偵聽一個事件
    $once 一次性偵聽一個事件
    $off 停止偵聽一個事件
慎用遞迴元件
儘量避免元件的迴圈引用
優先使用template來定義模板,而不是inline-template
$forceUpdate來強制更新view
元件包含大量靜態內容時,可使用v-once來標記,快取靜態內容

過渡 & 動畫

transition元件控制過渡動畫,可以給任何元素和元件新增進入/離開過渡
當插入或刪除transition中的元素時,vue會做如下處理

    自動嗅探元素是否使用了css過渡和動畫,適當時機新增/刪除類名
    元素的鉤子函式會在適當時機被呼叫
    元素既沒有鉤子函式也沒有css動畫,插入和刪除操作在下一幀立即執行(瀏覽器逐幀動畫機制)
    
過渡的類名

    v-enter/v-enter-active/v-enter-to
    v-leave/v-leave-active/v-leave-to

css動畫用法同css過渡,區別是類名v-enter不會在DOM插入後立即刪除,而是在animationend事件觸發時刪除
自定義過渡類名,使用以下屬性指定:

    enter-class/enter-active-class/enter-to-class
    leave-class/leave-active-class/leave-to-class

自定義類名優先順序高於普通的類名
使用type屬性設定transition或animation來申明vue使用的動畫型別
transition元件上使用duration來設定動畫執行的時間
可以使用鉤子函式
    
    beforeEnter/enter/afterEnter/enterCancelled
    beforeLeave/leave/afterLeave/leaveCancelled

    鉤子函式使用v-on指令繫結
    鉤子和結合過渡和動畫使用,也可以單獨使用
    在enter/leave中,必須使用done()來進行回撥,否則會同步呼叫,過渡或動畫會立即完成
對於純使用JavaScript來進行的動畫,推薦使用v-bind:css=“false”來取消css的檢測,減少css的影響
可使用apear設定初始渲染的過渡
    
    apear/apear-active/apear-to
    beforeApear/apear/afterApear/apearCancelled
多元素過渡,設定唯一key
過渡模式:

    In-out 新元素先過渡,完成後當前元素過渡離開
    out-in 當前元素先過渡,完成後新元素過渡進入
    預設行為:進入和離開同時發生
    
多個元件過渡使用動態元件實現
列表過渡 <transition-group>

    以真實元素呈現,預設為<span>,可使用tag更改呈現標籤
    過渡模式不可用
    內部需要唯一key
    
列表排序過渡,使用的是FLIP動畫,使用類名v-move來定義class

可複用性 & 組合

mixins混入屬性發生衝突時,以元件資料優先(一層屬性深度淺合併)
mixins混入方法發生衝突時,會將函式合併為一個數組,優先執行混入方法,其次執行元件方法
Vue.extend策略和mixins相同
慎用全域性混入
合併策略可以自定義(參考vuex的具體實現:Vue.config.optionMergeStrategies)
全域性自定義指令:Vue.directive()
區域性自定義指令:屬性directives,型別為Object
鉤子函式

    bind 指令第一次繫結到元素時呼叫,只執行一次,可用於一次性初始化設定
    inserted 元素插入父節點時呼叫
    update 所有VNode更新時呼叫,可能發生在子VNode之前
    componentUpdated 指令所在元件在VNode和其子VNode更新後呼叫
    unbind 指令與元素解綁時呼叫
    
鉤子函式都會被傳入以下引數:

    el 指令繫結元素,可操作DOM
    binding 指令描述物件
    vnode Vue生成的虛擬節點
    oldVnode 上一個Vnode,僅在update和componentUpdated中使用
    
指令接受所有合法的JavaScript表示式

渲染函式 & JSX

render函式接受createElement方法作為引數
createElement方法的作用是建立一個虛擬節點(VNode)
createElement引數比較複雜,參照官網:引數
元件樹中的VNodes必須唯一
render中的v-if/v-for可以使用if/else和map重寫
插槽使用this.$slot.default訪問,作用域插槽使用this.$scopeSlots.default訪問和設定
可以使用外掛babel-plugin-transform-vue-jsx支援JSX語法
將h作為createElement的別名是Vue生態的一個慣例,也是JSX要求的
函式式元件 關鍵詞:functional
函式式元件渲染開銷低,但相應的,它不會出現在Vue devtools的元件樹裡邊
函式式元件要求你自己實現同名特性的替換與智慧合併
Vue的模板實際編譯成了render方法實現的VNode,可以使用Vue.compile()方法來輸出編譯結果

外掛

外掛會為vue提供全域性的功能,包括但不限於以下幾種:

    新增全域性的屬性或方法,如vue-custom-element
    新增全域性的資源(指令、過濾器、過渡等),如:vue-touch
    通過全域性mixins新增一些元件選項,如:vue-router
    新增Vue例項方法,通過新增到Vue.prototype上實現
    一個獨立的庫,同時有自己的API,又實現以上部分功能,如:vue-router
    Vue外掛有一個公開的方法install,第一個引數是Vue構造器,第二個引數是一個可選物件。
    
外掛的使用通過全域性方法Vue.use(MyPlugin)使用,只會註冊一次外掛
在CommonJS中,應該始終顯式的呼叫Vue.use方法
社群外掛列表awesome-vue

過濾器

{{ msg | filter }}
<div v-bind=“msg | filter"></div>
全域性過濾器使用Vue.filter()建立
區域性過濾器使用物件屬性filters建立
過濾器函式總是接收表示式的值作為第一個引數,過濾器可以有多個,值依次向後傳遞
過濾器可以接收額外的引數

內容部門內容引自,很不錯兩篇文章