brain-store
v0.2.4
Published
数据仓容器,数据存取
Downloads
8
Maintainers
Readme
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 上的用户输入导致的状态变化。
以下是一个表示“单向数据流”理念的极简示意: 但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容 易被破坏:
- 多个视图依赖于同一状态。
- 来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者 通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置, 任何组件都能获取状态或者触发行为!
另外,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,我们的代码将会变得更结构化且易维护。
什么情况下我应该使用 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;
}
}
deprecate version
- 0.2.2
Licensing
MIT license