1. 程式人生 > >前端學習筆記Vue篇(2)

前端學習筆記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 ,使結構更加清晰