小程序模板網(wǎng)

微信小程序全局狀態(tài)管理,并提供Vuex的開發(fā)體驗(yàn)

發(fā)布時(shí)間:2018-05-09 14:53 所屬欄目:小程序開發(fā)教程

1. 概要

微信小程序的開發(fā)體驗(yàn)類似vue和react,但是卻沒有提供全局狀態(tài)管理的機(jī)制,所以狀態(tài)的共享只能通過屬性傳遞的方式來實(shí)現(xiàn)。這種做法在小規(guī)模的應(yīng)用中尚可以滿足開發(fā)效率,但是在復(fù)雜的應(yīng)用中組件的嵌套層次很深,屬性傳遞的路徑過長。

于是我就想利用小程序Page中的data對(duì)象來構(gòu)建一個(gè)全局store,這個(gè)store滿足一下幾點(diǎn)需求:

  • store可以被當(dāng)前頁面中任意一個(gè)組件訪問,并且這種訪問時(shí)直接的而不是通過屬性傳遞。
  • 全局store對(duì)于組件是相應(yīng)式的,也就是說store的變化可以使組件發(fā)生重繪。
  • 頁面和組件都可以修改store的狀態(tài),并且這種修改不破壞原來的響應(yīng)式。
  • 提供類似Vuex的開發(fā)體驗(yàn),減小學(xué)習(xí)成本。

先附上源碼 github地址

2. 使用

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

2.1 安裝

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

2.2 創(chuàng)建Page對(duì)象

這里我們通過wxappStore.createPage來創(chuàng)建。對(duì)比一下Store.js和原來的創(chuàng)建方法的區(qū)別


// 原來的創(chuàng)建方法
Page({
  data: {
    message: ''
  },
  onLoad: function () {
    this.setData({
        message: 'hello world'
    })
  }
})

// 增加全局狀態(tài)管理之后
import wxappStore from "../../lib/Store.js";

Page(wxappStore.createPage({
    // 第一個(gè)參數(shù)和原來傳入Page方法的option沒有區(qū)別。其中的data會(huì)作為全局共享對(duì)象來使用。
    data: {
        message: ''
    },
    onLoad: function () {
        // 通過dispatch方法,進(jìn)行一個(gè)異步操作。  
        this.store.dispatch({ 
            name: 'testAction',
            payload: 'hello world'
        });
        // 通過commit方法,修改全局狀態(tài)。
        this.store.commit({ 
            name: 'testMutation',
            payload: 'hello world'
        });
    }
}, 
// 第二個(gè)參數(shù)是一個(gè)對(duì)象,其中包含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方法有兩個(gè)參數(shù)。

第一個(gè)參數(shù)和原來傳入Page方法的option沒有區(qū)別。其中的data會(huì)作為全局共享對(duì)象來使用。

第二個(gè)參數(shù)是一個(gè)對(duì)象,其中包含mutations和actions

2.3 使用mutation

mutation和Vuex中的mutation類似,它通過同步的方式修改狀態(tài)??梢酝ㄟ^commit調(diào)用。

2.3.1 定義mutation

mutations在wxappStore.createPage的第二個(gè)參數(shù)中定義,它用于修改全局狀態(tài)。mutation通常同步的。mutation方法的參數(shù)是一個(gè)對(duì)象,包含三個(gè)屬性:

  • setData function: 用來修改全局狀態(tài),在微信小程序中直接修改狀態(tài)不會(huì)觸發(fā)頁面重匯。
  • payload object:修改的狀態(tài),可以是一個(gè)對(duì)象,也可以是String等基礎(chǔ)數(shù)據(jù)類型
  • data object:當(dāng)前狀態(tài)

mutations: {
    testMutation: function({ setData, payload, data }) {
        setData({
            message: payload
        });
    }
},

2.3.2 調(diào)用mutation

通過commit方法調(diào)用mutation,它的參數(shù)是一個(gè)對(duì)象,包含兩個(gè)屬性:

  • name String:mutation的名稱
  • payload Object:需要修改的狀態(tài),和Vuex的payload類似。

this.store.commit({ 
    name: 'testMutation',
    payload: 'hello world'
});

2.4 使用action

action和Vuex中action概念類似,通常包含異步操作,在異步操作完成后進(jìn)行commit操作。

2.4.1 定義action

action方法的參數(shù)是一個(gè)參數(shù),包含3個(gè)屬性:

  • commit function:執(zhí)行commit操作
  • payload Object:數(shù)據(jù)對(duì)象,和Vuex類型
  • data Object:當(dāng)前狀態(tài)

actions: {
    testAction: function ({ commit, payload, data }) {
        setTimeout(() => {
            commit({
                name: 'testMutation',
                payload: payload
            });
        });
    }
}

2.4.2 調(diào)用action

通過dispatch方法調(diào)用action,它的參數(shù)是一個(gè)對(duì)象,包含兩個(gè)屬性:

  • name String:action的名稱
  • payload Object:需要修改的狀態(tài),和Vuex的payload類似。

this.store.dispatch({ 
    name: 'testAction',
    payload: 'hello world'
});

2.5 創(chuàng)建Component

在Component中我們需要完成兩項(xiàng)工作

第一將全局狀態(tài)綁定到當(dāng)前組件的data屬性上,并將組件的data屬性綁定到頁面元素上。

第二組件需要使用commit或者dispatch完成全局狀態(tài)的修改。

這里Store.j通過wxappStore.createComp來創(chuàng)建Component,它會(huì)通過代理的方式為Component實(shí)現(xiàn)全局狀態(tài)管理的功能。


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

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

    // 改變?nèi)譅顟B(tài)  
    this.store.commit({
        name: 'testMutation',
        payload: (new Date()).toLocaleTimeString()
    })
  }
}))


<view>讀取全局狀態(tài):{{localtimeData}}</view>

2.5.1 全局狀態(tài)綁定

全局狀態(tài)綁定通過getGlobalData這個(gè)實(shí)例方法實(shí)現(xiàn),這個(gè)方法并不在小程序的運(yùn)行環(huán)境中,它是Store.js執(zhí)行的過程中插入到Component實(shí)例中的。

getGlobalData 不能再created回調(diào)中調(diào)用,應(yīng)為component的實(shí)例方法setData不能再created中調(diào)用。

getGlobalData的參數(shù)是一個(gè)對(duì)象,包含兩個(gè)屬性:

  • globalDataKey String:這個(gè)屬性表示需要全局狀態(tài)的屬性名,這個(gè)全局狀態(tài)將于component的本地狀態(tài)綁定。
  • localDataKey String:這個(gè)屬性表示本地狀態(tài)的屬性名,這個(gè)本地狀態(tài)將于全局狀態(tài)綁定。

// 綁定全局狀態(tài)
this.getGlobalData({ globalDataKey: 'localtime', localDataKey: 'localtimeData' });

2.5.2 改變?nèi)譅顟B(tài)

可以使用store.commit或者store.dispatch,store并不是小程序的運(yùn)行環(huán)境中內(nèi)置的,同樣是通過Store.js插入到每一個(gè)component實(shí)例中。它的使用方法和Page中的類似。

3. 這套框架的不足

  • Store.js借用了Page對(duì)象的data屬性來完成全局狀態(tài)管理,所以data屬性的職責(zé)并不單一。data屬性兼具了頁面ViewModel的功能和全局狀態(tài)的功能。但是Page中的data屬性本來也具有全局意義,所以兩者的沖突并不大。

  • component中的data屬性職責(zé)并不單一。它兼具了本地屬性的功能和綁定全局狀態(tài)的功能。而且直接通過setData修改component中的data并不能觸發(fā)全局狀態(tài)的改變,因?yàn)閐ata的作用域僅限于當(dāng)前component,必須通過store.commit或者store.dispatch觸發(fā)發(fā)全局狀態(tài)的改變。

  • 如果你發(fā)現(xiàn)其他問題,歡迎留言,我們共同進(jìn)步!



易優(yōu)小程序(企業(yè)版)+靈活api+前后代碼開源 碼云倉庫:starfork
本文地址:http://u-renovate.com/wxmini/doc/course/24375.html 復(fù)制鏈接 如需定制請(qǐng)聯(lián)系易優(yōu)客服咨詢:800182392 點(diǎn)擊咨詢
QQ在線咨詢