模型注册与使用

创建resa

const resa = createResa();

createResa会初始化redux store,支持用户传入额外的reducer和middleware。

模型注册

调用register函数,并传入新建的模型对象。

import AppModel from './AppModel';
const resa = createResa();
resa.register(new AppModel());

或者你可以将模型注册在namespace中:

resa.register(new AppModel(), 'namespace');

它们的区别是数据在redux state中的层级不同,不用namespace,模型的数据在根节点;使用namespace,模型的数据在namespace中。

如果同时使用上述两个方式注册appModel,那么redux的数据形状如下:

{
  appModel: {
    count: 0
  },
  namespace: {
    appModel: {
      count: 0
    }
  }
}

模型在同一namespace中不能重复注册

模型使用

调用resa上的Action创建函数来调用对应的reducer和effect,Action创建函数的名称和参数和你在模型中定义的 reducer和effect一模一样。

我们定义一个简单的模型。

@init({
    name: 'appModel',
    state: {
        count: 0
    }
})
export default class AppModel extends Model {
    @reducer()
    add(count: number) {
        return {
            count: this.state.count + count,
        };
    }

    @effect()
    * addAsync(count: number) {
        this.fulfilled({
            count: this.state.count + count,
        });
    }
}

调用reducer

如何调用这个reducer呢?你可以像下面这样:

// 先注册模型
const resa = createResa();
resa.register(new AppModel());

// 根据模型名称调用
resa.models.appModel.add(1);

add(1)函数会派发一个Action,格式如下:

{
  type: 'appModel/add',
  payload: {
    '0': 1
  }
}

调用effect

和调用reducer一样,直接调用effect函数名称:

resa.models.appModel.addAsync(1);

addAsync(1)会派发一个Action用来调用effect,格式如下:

{
  type: 'appModel/addAsync_ASYNC',
  payload: {
    '0': 1,
  },
}

this.fulfilled会派发一个Action用来调用内置reducer,格式如下:

{
  type: 'appModel/addAsync_ASYNC_FULFILLED',
  payload: {
    count: 1
  },
}

如果模型注册在namespace中,你可以使用namespace/${模型名称}调用模型

@init({
    name: 'appModel',
    namespace: 'namespace',
    state: {
        count: 0
    }
})
resa.register(new AppModel());
resa.models.['namespace/model'].add(1);

在react中使用模型

为了方便你在react中使用createResa返回的resa对象,我们提供了Provider组件和subscribe高阶函数。

Provider

将Provider组件包裹住其他组件替换掉react-redux的Provider组件

<Provider resa={resa}>
    <App />
</Provider>,

subscribe

subscribe和react-redux的connect函数用法类似,不过它更强大。

使用subscribe连接模型

const NewApp = subscribe({ appModel: AppModel }, [])(App);

subscribe函数的第一个参数是一个mapper,上述的代码表示将AppModel这个模型注入到App的props中,注入到props的属性名称为appModel,第二个参数dependence表示state的某个属性如果变化会导致组件更新。

组件更新的时机

subscribe函数生成的高阶组件会监听组件对state的使用,如果你使用了state的某一个属性,那么当这个属性变化的时候就会更新组件(组件不能是PureComponent)。 如果某个属性在回调函数中才会被使用,这时需要显式的告诉subscribe哪个属性变化后组件会更新。

这里要十分注意,为了保证性能(暂时使用defineProperty实现,如果用Proxy实现就没有性能问题),subscribe只会监听state的第一层属性。

举个例子,假设state的形状如下:

{
    a: 'aa';
    b: {
        c: 'cc',
    }
}

如果组件使用了a属性,那么a被修改时,组件会获得更新。如果组件使用了c属性,c被修改时,组件不会被更新。因此,这里要求修改state时,采用immutable的方式,推荐使用immer,下面是推荐的修改属性c的方式:

@reducer()
add() {
    return {
        b: produce(this.state.b, draftState => {
            draftState.c = 'ccc';
        })
    });
}

results matching ""

    No results matching ""