简化action属性更新
通常情况下,store
中会有很多属性,其中有些属性更新会很频繁,每一个属性都需要写一个action
函数去更新,当这种需要变更的属性越多时,会导致store
中代码量异常的庞大,可读性也会降低。就如下面代码一样:
class TestStore {
@observable info = {} as IInfo;
@observable list = [] as IList;
@action
setInfo = (value: IInfo) => {
this.info = value;
}
@action
setList = (value: IList) => {
this.list = value;
}
}
引入typescript
中keyof
关键字使用,可以将上述action
函数简化如下:
class TestStore {
@observable info = {} as IInfo;
@observable list = [] as IList;
@action
setValue = <T extends keyof TestStore>(key: T, value: this[T]) => {
this[key] = value;
}
}
简化store之间的相关依赖
callback实现Store之间的通信
比如StoreA中某个方法执行后需要调用StoreB中的方法
// /stores/StoreA.ts
class StoreA {
@action
methodA = (cb: () => void) => {
// coding...
if (cb) cb();
}
}
// /stores/StoreB.ts
class StoreB {
@action
methodB = () => {
// coding...
}
}
// /stores/index.ts
export default {
storeA: new StoreA(),
storeB: new StoreB(),
}
页面调用
// index.tsx
import React from 'react';
import stores from './stores/index.ts';
import Main from './components/Main.tsx';
const Index = () => {
return <Provider {...stores}>
<Main {...props}></Main>
</Provider>
}
// Main.tsx
import React from 'react';
interface IProps {
storeA?: StoreA;
storeB?: StoreB;
}
const Main = (props: IProps) => {
const { storeA, StoreB } = props;
const { methodA } = storeA;
const { methodB } = storeB;
const handleClick = () => {
methodA(methodB);
}
return <span onClick={handleClick}></span>
}
promise实现Store之间的通信
// /stores/StoreA.ts
class StoreA {
@action
methodA = () => {
return new Promise((resolve) => {
// coding...
resolve();
})
}
}
页面调用
const Main = (props: IProps) => {
const { storeA, StoreB } = props;
const { methodA } = storeA;
const { methodB } = storeB;
const handleClick = () => {
methodA().then(() => {
methodB();
});
}
return <span onClick={handleClick}></span>
}
通过根级Store调度子级Store实现通信
引入根级store,将上面store组织方式改成如下形式:
// /stores/StoreA.ts
class StoreA {
rootStore: RootStore;
constructor(rootStore) {
this.rootStore = rootStore;
}
@action
methodA = () => {
// coding...
this.rootStore.storeB.methodB();
}
}
// /stores/StoreB.ts
class StoreB {
rootStore: RootStore;
constructor(rootStore) {
this.rootStore = rootStore;
}
@action
methodB = () => {
// coding...
}
}
class RootStore {
storeA: StoreA;
storeB: StoreB;
constructor() {
this.storeA = new StoreA(this),
this.storeB = new StoreB(this),
}
}
// /stores/index.ts
export default {
rootStore: new RootStore(),
}
页面调用
const Main = (props: IProps) => {
const { storeA, StoreB } = props;
const { methodA } = storeA;
const { methodB } = storeB;
const handleClick = () => {
methodA();
}
return <span onClick={handleClick}></span>
}
降低store的颗粒度
有些项目页面的业务逻辑、交互异常的复杂,如果把这些业务逻辑都堆在一个store中将会使得store的代码量异常的庞大,就如上图store有着上千行的代码量。这将会严重降低代码的可读性,如果继续迭代甚至会影响后人的开发效率。
当然,我们可以上面拆分成多个store来解决问题,这种场景不是我本节考虑的,我想讲述的是以下这种场景:
假如我们要做这么一个表格,并且后端给的数据结构是这样子的:
quote数组中的每一个对象对应着每一个报价条目
如果每条报价条目数据需要改变时,就需要去遍历quote数组找到对应的报价条目对象,重新赋值,写一个函数就行了。如果报价条目相关的业务逻辑(校验、变更值等等)特别的多呢?那么也要书写很多的函数去实现,这些跟报价条目相关的业务代码都堆在一个store中肯定会使store更加的臃肿。
肯定有同学会说,把这部分拆分到一个独立的store中不就可以了吗?但是表格数据作为一个整体,这种业务拆分是不容易实现的,那么有没有其他方法呢?
肯定有的,在mobx中每一个报价条目对象都是一个observable对象,我们可以把这个对象抽出来放到另一个store中,而之前的store存放的只是一个引用,描述的可能不太清楚,附上代码说明一下:
// quotation.ts
class Quotation {
@observable quoteId: string = '';
@observable partNum: string = '';
@observable partName: string = '';
constructor(quotation: any) {
Object.assign(this, {...quotation});
}
@action
...
}
// tableStore.ts
class TableStore {
@observable tableData: ITable = [] as ITable;
assemble = (needResults: any, quotations: any) => {
const data: ITable = [];
needResults.forEach(v => {
quotations.forEach(p => {
if (p.demandItemId === v.demandItemId) {
data.push({
need: v,
quote: p.result.map(o => {
return new Quotation(o);
})
})
}
})
})
}
/** 获取报价项次、报价结果 */
@action
fetchTableData = async () => {
Promise.all([fetchNeedResults(), fetchQuotationResults()]).then((res) => {
if (res[0].code === 200 && res[1].code === 200) {
const needResults = res[0].data;
const quotations = res[1].data;
/** 组装表格数据 */
this.tableData = this.assemble(needResults, quotations);
}
});
};
}
这么设计store
的组织方式可以更加灵活的控制store
的颗粒度,同时也能很好的避免store
的巨大化以及多人操作同一个store
的场景。比如图中可以类似将“表格部分”拆分出“需求部分”、“报价部分”,当多人同时开发时,每一个人只需要负责自己模块中的样式、业务逻辑、数据存储,在一定程度上形成了一个闭环,对于每个开发来说都是有益的,而且这样一种组织代码的方式也会增强代码的可读性以及复用性,方便后期的维护。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。