一、简介
React-MVM
这是一个简单的状态管理框架,MVM 分别是 Model、View和Manager的意思。它的作用主要在于:
- 做数据层和视图层的分离,当然这里的数据层指的是全局数据;
- 它可以统一化开发模式,降低维护成本,提高开发效率;
- 用于组件开发时,它是个透明的盒子,这样就避免了常规组件开发碰到一些特殊需求时,需要帮忙添加回调函数,以及黑盒组件数据无法获取等问题。
二、基本概念
1、Model
Model 是用于管理数据状态的,可以用于定义state,设置更新state的updater函数,以及挂载一些handler即处理函数,后续也可以加入ref、hooks等支持,model的使用期望是对应某一块的功能,比如sdk这样的,与自定义的hooks封装相比,只是实现方式不同。
2、View
View 是视图层的入口,通过用 hooks 的方式去获取 Model中的state、updater以及handler等,这样将数据层的副作用抽离出去之后,视图层会看起来更加的干净。
3、Manager
Manager 即入口函数,它的作用是将Model层与View挂载在上面,做好它们之间的关联管理,通过ReactContext的方式将Model数据层的实例挂在顶层,这样View层的任一位置就可以通过这个context获取到model的数据,同时,由于model实例化之后并不会变化,因此完全不用担心context会导致其往下的视图层重新渲染。
三、示例
1、步骤一:设置Model
createStore
是用于构建model
所需要的store
的,构建完成之后,亦可以在model
层中的handlers
使用 store 去获取;
createModel
的返回值必须包含两个,name
和store
,name
是用来定义该model
构建之后,在 chrome 浏览器中Redux devtools
展示的名称,以及Manager
中绑定的名称,store
即createStore
构建出来的store
。
// ./_model.ts
import { createStore, createModel } from '@xxx/react-mvm';
const model = createModel(() => {
let name = 'model';
let initialState: State = {
count: 0,
};
let updaters = {
updateCount: (state: State, count: number) => {
state.count = count;
},
};
let store = createStore({
name,
initialState,
updaters,
});
let fetchCount = async () => {
let state = store.getState();
let updaters = store.updaters;
return;
};
return {
store,
handlers: {
fetchCount,
},
};
});
export default model;
type State = {
count: number;
};
2、步骤二:设置View
// ./_view.tsx
import React from 'react';
import model from './_model';
export default function View() {
const state = model.useState();
const updaters = model.useUpdaters();
const handlers = model.useHandlers();
const handleClickA = () => {
updaters.updateCount(state.count + 1);
handlers.fetchCount();
};
return (
<div>
<p>
{state.count}
<button style={{ marginLeft: 10 }} onClick={handleClick}>
+
</button>
</p >
</div>
);
}
3、步骤三:设置Manager
Manager
层则是很简单的将view
和model
挂到它上面即可,此外,还可以在preload
中做一些数据的预处理,同时,需要设置LoadView
,在preload
执行完之前,做一个loading
状态的渲染。
// ./index.ts
import { manager } from '@xxx/react-mvm';
import view from './_view';
import model from './_model';
let Page = manager({
View: view,
models: [model],
LoadView: null,
preload: async ({ models }) => {
let [localModel] = models;
let updaters = localModel.store.updaters;
// ...
},
});
export default Page;