前端學習筆記Vue篇(2)
1.Vue中資料雙向繫結的實現原理
首先我們要知道什麼是資料的雙向繫結
雙向繫結也就是我們平時所說的MVVM模式,即model,view,view-model
假如你在js中定義了一個物件
var cat = {
name: 'Tom'
}
假定我們通過某種方法使整個物件的資料和某個DOM節點關聯起來,以達到以下目的:
修改DOM節點的資料可以改變cat物件的資料,
修改cat物件的資料可以改變DOM節點的資料。
這便是我們所說的MVVM模式
搞清楚什麼是雙向繫結後,現在來說說Vue中的實現方式
vue.js 採用資料劫持結合釋出者-訂閱者模式的方式,通過Object.defineProperty()來劫持各個屬性的setter,getter,在資料變動時釋出訊息給訂閱者,觸發相應的監聽回撥。
這句話一時也許很難理解
首先在Vue中什麼是資料劫持,它就是通過Object.defineProperty()來獲取屬性的getter和setter方法,來進行資料的監控
其次什麼是釋出者-訂閱者模式,它有另一個更為熟悉的模式,即觀察者模式,這是一種javascript的設計模式。用通俗的話來講,它就像是微信公眾號和訂閱者的關係,作為訂閱者的你不必每天去請求公眾號給你發信息。
接下來就來看看它的實現原理了
上圖中,new MVVM()便是我們最終需要的,它的實現主要通過Observer,Compile,Watcher。
1.Observer使用Object.defineProperty()對資料物件的所有屬性進行監聽,如有變動可拿到最新值並通知訂閱者;
2.Compile是一個解析器,其目的就是渲染檢視。它通過解析模板指令,將模板中的變數替換成資料,然後初始化渲染頁面檢視,並將每個指令對應的節點繫結更新函式,新增監聽資料的訂閱者,一旦資料有變動,收到通知,更新檢視
3.Watcher便是這裡的訂閱者,作為連線Observer和Compile的橋樑,能夠訂閱並收到每個屬性變動的通知,執行指令繫結的相應回撥函式,從而更新檢視
以上便是Vue的雙向繫結實現原理
2.Vuex
什麼是Vuex?
簡單來說,Vuex是專門設計為Vue進行狀態管理的模式
Vuex在專案中的應用
首先初始化一個vue專案,並通過以下指令安裝vuex依賴:
npm install vuex -s
之後在專案的src目錄下新建一個store資料夾,形成以下檔案結構:
下面講解以下以上檔案的作用:
state
state中儲存資料的狀態,也就是你需要管理的資料儲存在state中
// state儲存資料的狀態
const state = {
val: {
count: 0,
type: Number
}
}
export default state
getter
getter相當於store的computed屬性,對資料進行加工過濾
export const count = (state) => {
return state.val.count
}
export const type = (state) => {
return state.val.type
}
這裡便是將val的count和type剝離了出來
mutation-type
mutation-type並不是vuex的核心概念,它是一種mutation的規範,定義mutation的函式名
export const ADD = 'ADD'
mutation
在vuex中,改變資料狀態的唯一方式就是提交mutation;
mutation獲取state中資料的狀態,並對其進行操作,需要注意的是mutation中進行的都是同步操作
import * as types from './mutation-type.js'
export default {
[types.ADD] (state) {
state.val.count += 1
}
}
actions
action和mutation的作用相同,但區別在於action中進行的是非同步操作,或者多個commit
import * as types from './mutation-type.js'
export default {
addAction ({commit}) {
setTimeout(() => {
commit(types.ADD)
}, 1000)
console.log('非同步執行的actions')
}
}
以上是提交一個add的mutation,commit是進行提交必要的引數,這裡使用setTimeout是為了體現非同步執行
store
store便是裝配以上內容後對外匯出的介面了,通常將裝配寫在store下的index.js中
import vue from 'vue'
import vuex from 'vuex'
import state from './state.js'
import * as getters from './getters.js'
import mutations from './mutations.js'
import actions from './actions.js'
import m1 from './modules/m1.js'
import m2 from './modules/m2.js'
vue.use(vuex)
export default new vuex.Store({
state,
getters,
mutations,
actions,
modules: {
m1,
m2
}
})
這裡的model之後再進行解釋
在元件中使用
有以下四個方法:
mapstate 獲取state資料
mapgetters 獲取getters資料
mapMutations 呼叫mutations方法
mapActions 呼叫actions方法
<div @click="add">{{count}}</div>
<div @click="addAction">{{count}</div>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
computed: {
// 獲取state中的資料
// ...mapState(['count'])
...mapGetters(['count'])
},
methods: {
...mapMutations({
'add': 'ADD'
}),
...mapActions({
'addAction': 'addAction'
})
}
上述4種函式呼叫的時候可以使用擴充套件運算子...直接呼叫
獲取資料的方式可以是
...mapState(['count'])//當state中的count和元件中的count名相同時
...mapState({'count': 'icount')當state中資料和元件中不同名時,這裡是icount
由於state中的資料是巢狀物件,所以使用mapGetters來獲取count
module
當元件數量增多時,其狀態也會變多,此時所有的狀態在同一個store中便會很複雜。
這時就可以建立不同的module,使用不同或相同的state,getters,mutations,actions ,使結構更加清晰