1 Star 7 Fork 0

l2j2c3 / mini-stores

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
MIT

mini-stores - 小程序多状态管理

前言

公司好几款产品使用钉钉小程序开发,和其他平台小程序一样,都没有官方实现的状态管理库,用过redux、vuex、mobx等状态管理库的前端小伙伴都知道,状态管理能很轻松帮我们解决很多跨页面跨组件通信问题。一开始写了一个Emitter类,用事件监听方式去实现全局状态管理,但这种方式相对繁琐且不够直观。于是网上寻找有没有更好的解决方案,最终找到了westore库,这是由腾讯开源团队研发的微信小程序解决方案,其中针对状态管理的实现很不错,而且还使用专门为小程序开发的JSON Diff 库保证每次以最小的数据量更新状态,比原生setData的性能更好。但由于不支持同时多例store及私有状态等,于是在看了源码之后,基于其核心原理重写了一版,另外根据自身理解做了如下改进:

1、优化渲染效率

每次更新store状态的时候,只对当前页面进行渲染,其他后台态页面延迟更新。这样可以大大减少同时setData的频次,提高渲染效率。

2、支持多例store

一个页面或者组件可以同时使用多个store,且不破坏原有私有状态的定义。

3、支持多平台

支持微信/支付宝/钉钉/百度/字节/抖音/QQ/京东等小程序使用。对于其他小程序,理论上也可以直接拿来用,使用时可自行验证。

安装

npm i mini-stores --save

也可以手动下载src/index.js文件放在项目中引用

使用

创建store

store继承于mini-stores提供的Store类,其中状态定义在data对象内,并支持函数计算属性(计算属性中的this指向store.data对象)

const create = require('mini-stores')

class Store extends create.Store {

  data = {
    title: '小程序多状态管理',
    language: "zh_cn",
    userName: '李狗蛋',
    deptName: '化肥质检部门',
    corpName: '富土康化肥厂',
    // 函数属性 - 可直接绑定到视图上
    description() {
      return `我是${this.userName},我在${this.corpName}工作`
    },
    a: {
      b: {
        // 深层嵌套也支持函数属性
        c() {
          return this.language + this.description
        }
      }
    }
  }

  onChangeLang() {
    if(this.data.language === 'zh_cn') {
      this.data.language = 'en_US'
    } else {
      this.data.language = 'zh_cn'
    }
    this.update()
  }
}

export default new Store()

页面内使用

在页面的初始化周期函数(onLoad)内,使用store.bind方法将页面实例绑定到store上,如store.bind(this, '$data'), 第一个参数this为当前页面实例,第二参数为该store在视图上使用的key名。

注意:该key在视图上使用时,并不是对应store,而是store.data值。另外定义key名注意不要和现有的私有变量同名,个人建议可以加个前缀(如$),这样可以一眼区分它来自全局状态。

import globalStore from '/stores/globalStore'
import indexStore from '/stores/indexStore'

Page({
  data: {
    privateData: '私有状态' // 私有状态还是通过原有的setData更新
  },
  onLoad() {
    // 绑定实例到store上,第二参数定义视图上使用的key名,命名随意,但注意不要和页面data内的私有变量同名
    indexStore.bind(this, '$index');
    globalStore.bind(this, '$data');
  },
  handleChangeTitle() {
    globalStore.data.title = '新标题'
    globalStore.update()
  },
  handleChangeName() {
    indexStore.changeName()
    indexStore.update() // 如果changeName方法内调用了this.update方法,此处可以省去调用indexStore.update()
  }
});

组件内使用

和页面内使用一样,在组件初始化时进行store绑定。注意下各平台组件初始化生命周期函数写法可能有所区别,根据对应官方文档来写即可。

import globalStore from '/stores/globalStore'
import indexStore from '/stores/indexStore'

Component({
  data: {
    privateData: '私有状态'
  },
  // 阿里系小程序
  didMount() {
    indexStore.bind(this, '$index');
    globalStore.bind(this, '$data');
  },
  // 微信小程序等大部分小程序
  lifetimes: {
    ready() {
      indexStore.bind(this, '$index');
      globalStore.bind(this, '$data');
    }
  },
  methods: {
    handleChangeTitle() {
      globalStore.data.title = '新标题'
      globalStore.update()
    },
    handleChangeName() {
      indexStore.changeName()
    }
  }
});

视图上使用

简单示例:

<view>
  <view>{{$index.title}}</view>
  <view>{{$data.language}}</view>
  <view>{{$data.description}}</view>
  <view>{{$index.a.b.c}}</view>
  <view>{{privateData}}<view>
</view>

更新状态

直接更改对应store.data内的值,最后调用store.upadte()即可。

注:store对象上不要重新定义update属性,避免覆盖

使用建议

1、不一定非要使用全局状态管理,涉及到跨页面组件通信时,再考虑使用也可。

2、使用时,建议将状态和逻辑提取到store上,页面只负责处理用户事件的监听和回调,这样的好处是:

  • 保持页面代码简洁,可以快速对页面的用户事件一目了然,更好把控业务。
  • 状态逻辑在独立的js上,方便实现逻辑复用,且更易于代码测试,对使用函数式编程非常友好。

以上是个人见解,在使用过程中有什么问题或建议可以在Issues进行反馈

快捷链接

MIT License Copyright (c) 2021 l2j2c3 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

简介

mini-stores - 小程序多状态管理库,解决跨页面组件通信,小巧高性能,新老项目都可使用,支持微信/支付宝/钉钉/百度/字节/抖音/QQ等小程序 展开 收起
JavaScript
MIT
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/l2j2c3/mini-stores.git
git@gitee.com:l2j2c3/mini-stores.git
l2j2c3
mini-stores
mini-stores
master

搜索帮助