一、雙向綁定原理 Vue2採用的是觀察者-發佈訂閱模式,利用Object.defineProperty實現對數據已定義屬性的監控(定義觀察者模式), 編譯DOM時解析v-model等屬性以及對input框等註冊事件實現UI和JS的交互(也就是註冊發佈訂閱這模式); 詳細的是主要是定義一個Observ ...
一、雙向綁定原理
Vue2採用的是觀察者-發佈訂閱模式,利用Object.defineProperty實現對數據已定義屬性的監控(定義觀察者模式),
編譯DOM時解析v-model等屬性以及對input框等註冊事件實現UI和JS的交互(也就是註冊發佈訂閱這模式);
詳細的是主要是定義一個Observe類實現對象的監控,通過Compile方法來解析DOM中的指令和替換DOM,每當遇到一個v-、{{}}等屬性
則生成一個Watcher,同時將Watcher添加到Dep中,當有屬性變化時則輪循Dep中所有的Watcher進行UI更新等操作
二、框架的優缺點
優點:1. 輕量級、提供了響應式編程概念,組件化思想
2. 採用虛擬DOM,渲染效率高
3. 生態完整
缺點:1. 由於頁面內容都是基於JS,所以SEO方面不是很友好
三、虛擬DOM和Diff演算法
虛擬DOM:web項目中比較消耗性能的就包含DOM的重排、重繪以及不斷的讀取DOM,但是JS的計算性能要比DOM的好很多,所以基於這個原因,Vue通過
生成虛擬DOM,記錄DOM節點名稱、類型、屬性以及事件等各種屬性,當數據有變化時,通過DIF演算法對比新舊虛擬DOM,以最小的性能代價找到DOM變化點,
然後只更新變化的DOM即可。
Diff演算法簡述:1. 為了提升性能,Diff演算法對比節點是只對比同一級節點,不做跨級對比
2. 對比節點,如果節點類型不同,則替換節點、類型相同則替換屬性或者文本、節點不存在則刪除、節點新增則增加
3. 如果存在子節點,設置頭尾指針,從節點兩端同時進行對比,同時移動指針下標值,如果endIndex>startIndex則終止迴圈
四、生命周期及其作用
1. beforeCreate: 初始化Vue實例,同時初始化周期事件,但是並沒有解析出$el以及沒有綁定data
2. created: 此時數據已經綁定,未解析出$el,但是$data已經綁定到vue中,這之後,beforeMount之前會判斷是否含有el元素,
沒有則生命周期結束(當執行$mount(el)時,繼續後續功能,因為此時已有$el),如果有則繼續判斷是否有template,
有temp,則編譯生成render函數,否則編譯outerHtml,如果要在created階段中進行dom操作,就要將操作都放在 Vue.nextTick() 的回調函數中
3. beforeMount: 完成data和el數據初始化,但是頁面中還是用vue占位符
4. mounted: 載入後html已經渲染(ajax請求可以放在這個函數中),把vue實例中的data里的message掛載到BOM節點中去
5. beforeUpdate: 重新渲染之前觸發,然後vue的虛擬dom機制會重新構建虛擬dom與上一次的虛擬dom樹利用diff演算法進行對比之後重新渲染
6. updated: 數據更新完成,dom也重新render完成
7. beforeDestory: 銷毀前執行($destroy方法被調用的時候就會執行),一般在這裡善後:清除計時器、清除非指令綁定的事件等等…’)
8. destoryed: 銷毀後 (Dom元素存在,只是不再受vue控制),卸載watcher、事件監聽、子組件等
五、組件間通信方式
1. 父傳子:採用v-model與props的方式進行通信,但是是單向的,子組件該值的改變並不會影響父組件;還可以採用Vuex
2. 子傳父:採用@emit事件由子組件向父組件冒泡數據或者採用$on的方式調用子組件的方式回調傳遞數據,同樣也是單向的;還可以採用Vuex
3. 兄弟組件:創建eventBus事件匯流排通訊,簡單方便不受兄弟組件的層級關係限制;子1上報給父,父下發給子2,數據傳遞邏輯較亂,不能適用於多層級的兄弟關係;還可以採用Vuex
4. 父子組件的值同步修改:父組件中綁定v-model:example,子組件設置emits: ['update:example'], 當子修改後,採用$emit('update:example')就可以將父組件的值同步改變
六、Vuex的使用
組件之間經常會有數據之間相互通信,但是多層嵌套傳值複雜度就會增加。因此vuex就是把常用的變數抽取出來組成一個全局單例模式進行管理,
將共用的數據放到vuex,任何組件都可以使用,一旦數據修改,所有引用數據的組件的值都會同步修改,通過commit('***')進行修改,通過mapState把全局的state和getters映射到組件中,
總共有五個屬性:
state: 存放一些狀態(簡單說就是變數),狀態被修改後,所有引用的地方都會修改
getters: 有時候需要從state中派生出一些狀態,比如對狀態根據某個條件進行過濾
mutations:定義如何修改state中的狀態,更新state值的唯一方法就是提交mutation,比如:store.commit('****')
action:專門用來解決mutations只有同步無非同步的問題,使用commit賦值
modules:項目特別複雜的時候,可以讓每一個模塊擁有自己的state、mutation、action、getters,使得結構非常清晰,方便管理
七、路由的使用
1. 全局路由:beforeEach、afterEach方法當導航觸發時會被順序執行,可以進行添加token以及做跳轉攔截等
2. 單個路由:beforeEnter
3. 組件間路由:beforeRouteEnter beforeRouteUpdate beforeRouteLeave
八、需要註意的知識點
1. v-model和v-bind的差別:
v-bind是單向綁定或者叫屬性綁定,支持修改屬性值,可簡寫為:attr
v-model是雙向綁定,可用在輸入標簽中
v-bind和v-model同時使用時 model優先順序更高
2. 為什麼數組的值變化了不能同步更新到UI:
Vue2對數據的監聽主要是通過defineProperty方法實現的,通過試驗可以得知該方法可以監控已有屬性的變化,但是Vue2依舊沒有實現這個能力
原因主要是考慮到性能問題:一個對象的屬性個數一般是有限的,所以對屬性進行監控消耗性能不大,但是數組可能會有成千上萬,
對每個屬性監控性能消耗太大,付出和用戶體驗不成正比,故而沒有實現
3. computed和watch的使用和區別:
都是以vue的依賴追蹤機製為基礎,都是為了當某一個數據發生變化時,所有依賴這個數據的數據發生變化
watch: 一個數據影響多個數據
computed:一個數據受多個數據影響,支持set、get方法(預設是get),有緩存效果