阿里小程序数据共享(状态管理)方案

1,200 阅读3分钟

熟悉在小程序原理的同学其实应该认可应该是算是MPA,而却又有全局的作用域scope,全局对象 my、app(通过App定义 getApp获取) 等。这样多页面、组件间就可以共享数据 。

自己手动实现

通常在原生开发方式下,我们可以在App中定义一个对象来统一存储全局数据:

//app.js
App({
    globalData:{
        count: 123
    }
})

这样定义好后,在页面生命周期中去主动获取数据并同步设置到当前页面data中:

//a.js
let { globalData } = getApp();
Page({
    onLoad(){
        this.setData({
            globalData
        })
    },
    add(){
        globalData.count  = globalData.count + 1;
        this.setData({
            globalData
        })
    }
})

设置后页面模板中可以使用此变量:

<view>{{globalData.count}}</view>

需要注意的是,每次更新globalData对象,要同时去setData更新页面和组件的data数据。切换页面(返回页面)每个页面都需要监听对应生命周期主动更新data。同样的,组件也可以实现同步全局数据,思路是一样只是组件生命周期不一样,当然被动更新方式还有一些区别,这里不细述了。

上面通过自己实现了数据全局共享,但是不够简洁、优雅、和具体页面组件耦合度也很高。

miniapp-spore

接下来我们介绍miniapp-spore这个框架,说框架感觉它很小很轻量更像一个库一样,而且原理是相同的,和前面代码一样只是做了封装。

首先运行 npm i miniapp-spore -s 安装包或者开发者工具中添加此包:

框架首要特性就是全局数据管理:

import { Store } from "miniapp-spore";

new Store('$store', { count: 1024 })

Store 类实例化后,就自动同步到了每个页面。每个页面axml模板内可以使用此变量。

<view>{{$store.count}}</view>

更新数据使用setData方法

let store = new Store('$store', { count: 1024 })

//将全局数据count加1
store.setData({
	count: store.data.count + 1
});

在页面更新数据需要在页面拿到实例调用对应方法即可,通常将store放到app上,方便页面/组件获取到store对象

app.js

import { Store } from "miniapp-spore";

let store = new Store('$store', { count: 1024 })

App({
	store
})

pages/index/index.js 页面拿到实例后调用对应setData更新全局数据

let store = getApp().store;

//方便拿到store
Page({
	onLoad(){
		store.setData({
			count: store.data.count - 1
		}, ()=>{
			console.log('数据已更新')
		})
	}
});

对于更新全局对象是通过setData,这个方法用法和页面组件的简直一模一样。使用起来没有任何心智负担。同样的,更新数组也有$spliceData 方法。

//在 obj.arr 下的这个数组下标1后插入 'a','b','c'
store.$spliceData({
  'obj.arr': [1, 0, 'a','b','c']
});

这样调用后页面就自动更新,切换到b页面后也数据也更新了。

组件的全局数据,需要手动配置一下stores,页面只有一个更新性能开销还能接受,组件在页面内的个数就是未知了,如果组件过多性能开销特别大,因此,组件需要全局变量的组件上配置stores字段(组件只更新在stores中配置的全局数据),另外可以通过页面对props传递给组件全局数据来提升性能。

components/test/test.js

let store = getApp().store;

Component({
  // 新增可定义此stores字段
  stores: [
    store,
	//... 支持多个store实例
  ],

  data: {},
  props: {},
  didMount() {
  
  },
});

最后发一个 在线演示示例