熟悉在小程序原理的同学其实应该认可应该是算是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() {
},
});
最后发一个 在线演示示例。