1.3.2 • Published 2 years ago

beleaf v1.3.2

Weekly downloads
3
License
MIT
Repository
github
Last release
2 years ago

begonia-leaf 介绍

beleaf(begonia-leaf)是配合begonia框架的状态管理库,仅用于小程序开发。

微信小程序基础库版本

^2.2.1

何时使用数据状态管理

当随着应用的规模扩大,数据状态管理将成为程序关注的重点,多个组件需要取得一致的状态时,为了更有利于开发、信息共享和管理,选择之一就是引入状态管理库。比如redux或者mobX

                    Service
                    |  ^
                    v  |
View - ViewModel--->action--dispatch
            |               |
            |            reducers
            |               |
            getters--state--|

结合小程序开发的实际,我们希望可以有对象能时刻监控state的变化,将我们关注(订阅)的分支变化进行报告。 此外,我们还想有办法对更新后的数据进行加工,最后再进行setData生效。当然,如果能结合begonia所建立的VMP进行延迟提交,则更为有利。

因此,我们将进行如下变化:

  setData           Service
  |     ^            |  ^
  |     |            |  |
  |     VMP          |  |
  V     |            v  |
View---ViewModel--->action--->dispatch
        ^                        |
        |                     reducers
        |                        |
  WatchManager<-----------state<-|

这就是beleaf的内部结构:

  • bex.js beleaf模块的入口,以及主要api提供者,不仅提供装载到begonia上的方法,而且会将特殊的方法装饰到小程序实例和vmp实例上。
  • ReduxLite.js 简版的redux实现
  • WatchManager.js 通过对state变化的监控,提供订阅state某个分支变化的api,并为vmp实例提供类似观察者处理函数的功能,可以进行再加工。

快速使用

1. 安装

请在小程序项目的根目录下(即 project.config.js 中的 miniprogramRoot 字段)执行npm安装:

$ npm install beleaf

接下来,我们需要做的,就是使用微信开发者工具中的工具->构建npm命令,对已经安装好的npm模块进行构建。 关于如何使用微信开发者工具构建npm模块,你可以参考官方文档

2. 建立store目录和store.js文件

为了便于管理和维护,我们可以在项目开发根目录中建立一个store目录,将对beleaf模块的配置放入其中。

other dir
|
|-store
|   |-store.js  入口文件,配置bex
|   |-user.js   state分支文件,例如,处理用户信息的user.js
|   
|   
|
other dir

现在以一个store.js为例:

// store.js
import BE from 'begoina';     //导入begonia入口模块
import bex from 'beleaf';     //导入beleaf的入口文件

import user from './user';      //导入分支文件user.js

//将beleaf装载到begoina的主模块上
BE.use(bex);

const SET_SYS_ID = 'setSysId';

//创建一个store实例
const store = bex.createStore({
  // 可以打开debug模式,查看输出
  debug: true,
  // 放置于此的state会被分配到root分支
  state: {
    sysId: 0
  },
  getters: {
    sysId: state => state.sysId
  },
  actions: {
    setSysId({ dispatch }, id = 0) {
      dispatch(SET_SYS_ID, 12345);
    }
  },
  reducers: {
    [SET_SYS_ID](state, data = 0) {
      state.data = data;
    }
  },
  //在modules字段下,装载定义的state分支对象
  modules:{
    user
  }
});

//导出store实例对象
export default store;

由于在上面例子中我们还导入了一个user.js作为state分支,下面我们来创建它。 这里以用户信息分支user.js为例,了解一下如何创建一个state分支:

//user.js

/**
 * user state 相关
 */
//=====================================================
//导入用于远程加载用户信息的UserService
import UserService from '../services/UserService';
//=====================================================
//reducer名常量
const SET_USER = 'setUser';
const ADD_USERS = 'addUsers';

export default {
  //state分支对象
  state: {
    users:{},
    userId:0
  },
  //访问分支的getter方法
  getters: {
    userId: state => state.userId,
    currentUser: state => UserService.combineUserInfo(state.userId, state.users) 
  },
  //action函数集合
  actions: {
    /**
     * 启动登录
     */
    setupLogin({ dispatch }) {
      return UserService.setupLogin()
        .then(function(res) {
          let user = res.user;
          if(!user || !user.id){
            return;
          }
          //将用户对象加入state分支
          dispatch(ADD_USERS, {
              [user.id]:user
          });
          //设置当前的用户id
          dispatch(SET_USER, user.id);        
        })
        .catch(function(error) {
          console.error("In user state setupLogin,catch an error.", error);
        });
    }  
  },
  //修改分支的reducer函数,注意数据的不可变性
  reducers: {
    [ADD_USERS](state, data = {}){
      // 为保持数据的不可变性,创建一个新的对象
      state.users = Object.assign({}, state.users, data);
    },
    [SET_USER](state, data = 0){
      state.userId = +data;
    }
  }
};

请注意,在上面的例子中的setupLogin()方法中,我们对参数进行了解构,在函数的内部声明了dispatch。 其实方法的第一个参数是一个对象,它包含了一些与store映射的属性和方法,但它并不是store对象本身。 对象的结构如下:

{
  dispatch: (type, payload) => {},
  actions: object,
  getters: object,
  state: object, // 根级state中当前分支下的state,相当于store.state[branch]
  root: object // 根级state,相当于store.state
}

3. 在小程序页面和组件实例中,订阅关注的state分支属性以及发出acton

当有关store和user分支都准备好后,我们来看如何在小程序的页面和组件实例中使用状态管理。 注意,虽然App实例(在app.js中定义的对象)不具有setData方法,我们仍然可以使用beleaf提供的方法, 订阅state分支属性变动。

import BE, { PAGE } from 'begonia';
import { mapActions } from 'beleaf';

BE({
  /**
   * 页面的初始数据
   */
  data(){
    return {

    };
  },
  // beleaf专有的字段,内部会解析该对象,并为实例注册观察者
  observed: {
    userId:{
      // 当userId发生变化时,此函数将会被调用,其中this的引用为小程序页面实例
      update(value) {
        console.log('In vh page, get the userId----->', value);
      },
      // 设置不获取userId的初始值,只有当userId真正产生变化的时候
      // 才会得到响应,这项设置是可选的
      immediate: false
    }
  },
  /**
   * 生命周期函数--监听页面加载
   */
  created (options) {
    //访问store实例
    let store = this.$store;
    //查看state状态树
    let state = this.$store.state;

    //通过getters对象访问具体的state属性
    let list = this.$getters.groupList;

    //发起一个action,引起状态变更
    this.setupLogin();
  },
  // ...
  ...mapActions(['setupLogin'])
  })(PAGE);

更多关于beleaf的使用细节,您可以访问模块的GitHub项目仓库,详细了解。

说明

诚如所见,为方便使用,beleaf在API的名称设计上借鉴了很多vuex框架的API名称, 不过内部实现和实际使用还是不同的。限于其使用的场景,beleaf追求够用即好。

开源协议

MIT

1.3.2

2 years ago

1.3.1

3 years ago

1.3.0

3 years ago

1.2.0

3 years ago

1.1.0

3 years ago

1.0.14

5 years ago

1.0.13

5 years ago

1.0.12

5 years ago

1.0.11

5 years ago

1.0.10

5 years ago

1.0.9

5 years ago

1.0.8

5 years ago

1.0.7

5 years ago

1.0.6

5 years ago

1.0.5

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago

1.0.1

5 years ago

1.0.0

5 years ago