结构
Vanex 中负责存储数据,同步/异步的数据操作,其结构如下:
const xxxModel = {
name: 'xxxModel',
data: {
// 数据存放
globalCount: 0,
login: {
abc: 'test'
},
...
},
syncs: {
// 所有的同步操作
// 在组件中可以通过 this.xxxModel.loginResetAbc('A new Val') 调用
loginResetAbc(arg) {
this.login.abc = arg;
},
...
},
effects: {
// 所有的异步操作,必须是 async function
// 在组件中可以通过 await this.xxxModel.loginFetch() 调用
async loginFetch() {
const data = await fetch(...);
return data.xxx;
}
//...
},
computed: {
// 响应式的计算值
get nameWithCount() {
// 当在组件中依赖了 nameWithCount 时,abc 或者 globalCount 改变时
// 都会触发该值的重新计算并且触发组件重新 render
return `${this.abc} - ${this.globalCount}`;
}
//...
},
autorun: {
// 当依赖的值发生变动时被执行
someName() {
if (this.abc) {
// abc 获得新的值时
this.globalCount = this.globalCount + 1;
}
},
// ...
},
};
操作数据
上面我们可以看到,我们既可以在组件中直接操作数据,也可以在 Model 的 syncs/effects
中操作数据,但是我们更推荐在 Model 中操作数据。一方面是为了将操作数据的逻辑分离,另一方面 Vanex 针对 Model 中的数据操作做了优化,一个 sync 或者 一个 effect 中的所有数据操作只会触发一次重新渲染。
注册
要使用一个 model,使用 Vanex 的 start 函数中注册。
import { start } from 'vanex';
start({
component: App,
container: '#root',
models: {
xxxModel,
//... 其他 model
}
});
在组件中使用
为了在组件中访问到 model,我们可以通过 @vanex
API 来注入相应的依赖。
import { vanex } from 'vanex';
@vanex('xxxModel', 'yyyModel', ...)
class XComponent {
render() {
// 可以通过 `this.xxxModel` 访问注入的 xxxModel
// 通过 `this.props.xxxModel` 也可以访问,但不推荐
const { name, someSync } = this.xxxModel;
return <div>
<Button onClick={() => someSync('test')}>{name}</Button>
</div>
}
}
纯函数组件
由于纯函数组件没有 class 也没有 this,所以我们只注入到 props
中。
import { vanex } from 'vanex';
const PureComponent = vanex('xxxModel')(
({ xxxModel }) => <div>
{xxxModel.name}
</div>
);
原有的注入方法
你也可以使用 mobx-react 提供的注入方法,这种方式只注入到 props 中而不注入到 this。
相关的文档参见 https://github.com/mobxjs/mobx-react ,如果你有更复杂的需求可以考虑使用该 API。
import { inject, observer } from 'vanex';
@inject('xxxModel')
@observer
class XComponent {
render() {
// 这种方式只注入到 `this.props.xxxModel`
const { name, someSync } = this.props.xxxModel;
return <div>
<Button onClick={() => someSync('test')}>{name}</Button>
</div>
}
}
Model 的拆分
通常我们推荐把不同模块的数据放在分开的 Model 中,然后一个组件注入一个或者多个 Model,下面是一个相对复杂的 Model 使用例子: