微信小程序全局状态管理,并提供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. 写无缺累,原理等下次更新吧。。。。

相关文章
相关标签/搜索