微信小程序全局狀態管理,並提供Vuex的開發體驗

1. 概要

微信小程序的開發體驗相似vue和react,可是卻沒有提供全局狀態管理的機制,因此狀態的共享只能經過屬性傳遞的方式來實現。這種作法在小規模的應用中尚能夠知足開發效率,可是在複雜的應用中組件的嵌套層次很深,屬性傳遞的路徑過長。html

因而我就想利用小程序Page中的data對象來構建一個全局store,這個store知足一下幾點需求:vue

  • store能夠被當前頁面中任意一個組件訪問,而且這種訪問時直接的而不是經過屬性傳遞。
  • 全局store對於組件是相應式的,也就是說store的變化可使組件發生重繪。
  • 頁面和組件均可以修改store的狀態,而且這種修改不破壞原來的響應式。
  • 提供相似Vuex的開發體驗,減少學習成本。

先附上源碼 github地址react

2. 使用

咱們先跳過原理來看使用方法。git

2.1 安裝

將Store.js放入微信小程序項目的文件夾中,例如/lib/Store.js。github

2.2 建立Page對象

這裏咱們經過wxappStore.createPage來建立。對比一下Store.js和原來的建立方法的區別小程序

// 原來的建立方法
Page({
  data: {
    message: ''
  },
  onLoad: function () {
    this.setData({
        message: 'hello world'
    })
  }
})
// 增長全局狀態管理以後
import wxappStore from "../../lib/Store.js";

Page(wxappStore.createPage({
    // 第一個參數和原來傳入Page方法的option沒有區別。其中的data會做爲全局共享對象來使用。
    data: {
        message: ''
    },
    onLoad: function () {
        // 經過dispatch方法,進行一個異步操做。  
        this.store.dispatch({ 
            name: 'testAction',
            payload: 'hello world'
        });
        // 經過commit方法,修改全局狀態。
        this.store.commit({ 
            name: 'testMutation',
            payload: 'hello world'
        });
    }
}, 
// 第二個參數是一個對象,其中包含mutations和actions
{
    mutations: {
        testMutation: function({ setData, payload, data }) {
            setData({
                message: payload
            });
        }
    },
    actions: {
        testAction: function ({ commit, payload, data }) {
            setTimeout(() => {
                commit({
                    name: 'testMutation',
                    payload: payload
                });
            });
        }
    }
}))

wxappStore.createPage方法有兩個參數。微信小程序

第一個參數和原來傳入Page方法的option沒有區別。其中的data會做爲全局共享對象來使用。微信

第二個參數是一個對象,其中包含mutationsactionsapp

2.3 使用mutation

mutation和Vuex中的mutation相似,它經過同步的方式修改狀態。能夠經過commit調用。框架

2.3.1 定義mutation

mutations在wxappStore.createPage的第二個參數中定義,它用於修改全局狀態。mutation一般同步的。mutation方法的參數是一個對象,包含三個屬性:

  • setData function: 用來修改全局狀態,在微信小程序中直接修改狀態不會觸發頁面重匯。
  • payload object:修改的狀態,能夠是一個對象,也能夠是String等基礎數據類型
  • data object:當前狀態
mutations: {
    testMutation: function({ setData, payload, data }) {
        setData({
            message: payload
        });
    }
},

2.3.2 調用mutation

經過commit方法調用mutation,它的參數是一個對象,包含兩個屬性:

  • name String:mutation的名稱
  • payload Object:須要修改的狀態,和Vuex的payload相似。
this.store.commit({ 
    name: 'testMutation',
    payload: 'hello world'
});

2.4 使用action

action和Vuex中action概念相似,一般包含異步操做,在異步操做完成後進行commit操做。

2.4.1 定義action

action方法的參數是一個參數,包含3個屬性:

  • commit function:執行commit操做
  • payload Object:數據對象,和Vuex類型
  • data Object:當前狀態
actions: {
    testAction: function ({ commit, payload, data }) {
        setTimeout(() => {
            commit({
                name: 'testMutation',
                payload: payload
            });
        });
    }
}

2.4.2 調用action

經過dispatch方法調用action,它的參數是一個對象,包含兩個屬性:

  • name String:action的名稱
  • payload Object:須要修改的狀態,和Vuex的payload相似。
this.store.dispatch({ 
    name: 'testAction',
    payload: 'hello world'
});

2.5 建立Component

在Component中咱們須要完成兩項工做

第一將全局狀態綁定到當前組件的data屬性上,並將組件的data屬性綁定到頁面元素上。

第二組件須要使用commit或者dispatch完成全局狀態的修改。

這裏Store.j經過wxappStore.createComp來建立Component,它會經過代理的方式爲Component實現全局狀態管理的功能。

import wxappStore from "../lib/Store.js";

Component(wxappStore.createComp({
  data: {
    localtimeData: ''
  },
  ready: function () {
    // 綁定全局狀態
    this.getGlobalData({ globalDataKey: 'localtime', localDataKey: 'localtimeData' });

    // 改變全局狀態  
    this.store.commit({
        name: 'testMutation',
        payload: (new Date()).toLocaleTimeString()
    })
  }
}))
<view>讀取全局狀態:{{localtimeData}}</view>

2.5.1 全局狀態綁定

全局狀態綁定經過getGlobalData這個實例方法實現,這個方法並不在小程序的運行環境中,它是Store.js執行的過程當中插入到Component實例中的。

getGlobalData 不能再 created回調中調用,應爲component的實例方法 setData不能再 created中調用。

getGlobalData的參數是一個對象,包含兩個屬性:

  • globalDataKey String:這個屬性表示須要全局狀態的屬性名,這個全局狀態將於component的本地狀態綁定。
  • localDataKey String:這個屬性表示本地狀態的屬性名,這個本地狀態將於全局狀態綁定。
// 綁定全局狀態
this.getGlobalData({ globalDataKey: 'localtime', localDataKey: 'localtimeData' });

2.5.2 改變全局狀態

可使用store.commit或者store.dispatchstore並非小程序的運行環境中內置的,一樣是經過Store.js插入到每個component實例中。它的使用方法和Page中的相似。

3. 這套框架的不足

  • Store.js借用了Page對象的data屬性來完成全局狀態管理,因此data屬性的職責並不單一。data屬性兼具了頁面ViewModel的功能和全局狀態的功能。可是Page中的data屬性原本也具備全局意義,因此二者的衝突並不大。
  • component中的data屬性職責並不單一。它兼具了本地屬性的功能和綁定全局狀態的功能。並且直接經過setData修改component中的data並不能觸發全局狀態的改變,由於data的做用域僅限於當前component,必須經過store.commit或者store.dispatch觸發發全局狀態的改變。
  • 若是你發現其餘問題,歡迎留言,咱們共同進步!

4. 寫無缺累,原理等下次更新吧。。。。

相關文章
相關標籤/搜索