一、简介
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.tsimport { 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.tsximport 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.tsimport { 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;

