brain-store
    TypeScript icon, indicating that this package has built-in type declarations

    0.2.3 • Public • Published

    brain-store

    一个抽象的 OOP 数据仓库,以 IOC 思想来管理数据的注册和读取,它很抽象,如果你要在 React 中,这个时候你可以借助 mobx 与 brain-store 结合来管 理数据,它只是一个数据仓库管理方案,只管理数据注册和数据正确读取,本身数据属性不具备响应式数据特性,如果你需要在 react,vue,angular 等 框架中应用,你还需要结合其框架本身特性来做处理

    数据归类

    通常我们对数据所应有场景做了一些简单归类,例如跟随应用整个生命周期的Application类型,基于路由的History类型,基于路由的数据,在路由 push 到不同页面时,我们都有一份页面自身独有的状态数据,它不受其他页面操作干扰,也不于其他页面状态产生依赖,在页面回退后,会自动销毁状态, 降低内存消耗。

    什么是状态管理模式(认识状态管理)?

    让我们从一个简单的 angular 计数应用开始:

    import React from 'react';
    export class AppComponent extends React.Component {
      count: number = 0;
      handleIncrement() {
        this.count++;
      }
      render() {
        <div onClick={this.handleIncrement.bind(this)}>{this.increment}</div>;
      }
    }

    这个状态自管理应用包含以下几个部分:

    • state,驱动应用的数据源;
    • view ,以声明方式将 state 映射到视图;
    • actions,响应在 view 上的用户输入导致的状态变化。

    以下是一个表示“单向数据流”理念的极简示意: store-img 但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容 易被破坏:

    • 多个视图依赖于同一状态。
    • 来自不同视图的行为需要变更同一状态。
      对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者 通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

    因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置, 任何组件都能获取状态或者触发行为!

    另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。

    什么情况下我应该使用 brain-store?

    虽然 brain-store+mobx 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。如果您不打算开发大型单页应用,使 用 brain-store 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 brain-store。

    use

    npm install brain-store --save
    or
    yarn add brain-store -S

    定义数据状态类型基类

    Application类型(默认)

    /* 定义基类*/
    import Store, { StoreModules } from 'brain-store';
    export default class StoreBase extends Store {
      static meta = {
        ...Store.meta,
        namespace: project.name,
      };
    }
    @StoreModules('UserListStore')
    class UserListStore extends StoreBase {
      payloadModel = '';
    }

    ui-store 详情场景见数据归类介绍

    import { action, computed, observable } from 'brain-store';
    import { resource, StoreModules } from 'brain-store';
    const User = resource('PMS/User');
    /* UI基类*/
    class UiStoreBase extends Store {
      static meta = {
        ...StoreBase.meta,
        lifecycle: Lifecycle.History,
        namespace: `${StoreBase.meta.namespace}.ui`,
      };
    }
    @StoreModules('UserListStore')
    class UserListUiStore extends UiStoreBase {
      name = 'default';
    }

    eventScopes

    当你 store 拆分的比较细的时候,当执行某个事件操作需要通知多个 store 中数据更新,这个时候我们通过在事件函数中直接调用各个 store 方法进行更 新操作,这虽然能解决,但显然不算是比较好的解法,这个时候我们可以定义一个事件触发器,当触发器中某个操作执行时,在需要执行响应动作的 store 中注入特定事件即可,例如下

    import { resource, StoreModules } from 'brain-store';
    const User = resource('PMS/User');
    interface IUserInfo {
      userName: string;
      age: number;
    }
    const manage = new StoreManage();
    const user = resource('PMS/User') as IResource;
    @StoreModules('UserListStore')
    class UserListStore extends StoreBase {
      static meta = {
        ...StoreBase.meta,
        eventScopes: [user],
      };
      userInfo: IUserInfo = (null as unknown) as IUserInfo;
      onEvent(event: IResourceEvent<IUserInfo>) {
        if (typeof event.payload === 'object') {
          this.userInfo = event.payload;
        }
      }
    }
    
    @StoreModules('UserEditStore')
    class UserEditStore extends StoreBase {
      static meta = {
        ...StoreBase.meta,
        eventScopes: [user],
      };
      userInfo: IUserInfo = (null as unknown) as IUserInfo;
      triggerEvent(payload) {
        this.context.dispatch(user.created, payload);
      }
      onEvent(event: IResourceEvent<IUserInfo>) {
        if (typeof event.payload === 'object') {
          this.userInfo = event.payload;
        }
      }
    }
    const payload = { userName: 'xiaoming', age: 22 };
    let listState: InstanceType<typeof UserListStore> = manage.getState(UserListStore, true);
    let editState = manage.getState(UserEditStore, true);
    editState.triggerEvent(payload);

    contextTypes

    在使用 store 时候,经常遇到不同 store 之间需要获取其他 store 实例,这个时候就可以使用它了

    interface IUserInfo {
      userName: string;
      age: number;
    }
    interface IContext {
      app: AppStore;
    }
    
    //@ts-ignore
    class StoreBases extends Store<IContext> {
      static meta = {
        ...Store.meta,
        namespace: 'pms',
      };
    }
    @StoreModules('UserListStore')
    //@ts-ignore
    class UserListStore extends StoreBases {
      static meta = {
        ...StoreBase.meta,
        contextTypes: { app: AppStore },
      };
      userInfo: IUserInfo = (null as unknown) as IUserInfo;
      getContextAppStore() {
        return this.context.app;
      }
    }
    const manage = new StoreManage();
    let state = manage.getState(UserListStore, true);
    
    let appStates = manage.getState(AppStore);
    let appStore = state.getContextAppStore();

    in brain-store-react to use

    import React from 'react';
    import Store, { bind ,inject} from 'brain-store';
    import {observable} from 'mobx'
    @StoreModules('UserListStore')
    //@ts-ignore
    class UserListStore extends Store {
      @observable userName=''
    }
    @bind({ store: UserListStore })
    export default class User extends React.Component {
      @inject(UserListStore)
      userListStore!:UserListStore
      render() {
        null;
      }
    }

    Licensing

    MIT license

    Install

    npm i brain-store

    DownloadsWeekly Downloads

    37

    Version

    0.2.3

    License

    MIT

    Unpacked Size

    64.3 kB

    Total Files

    24

    Last publish

    Collaborators

    • duanguang