3
头图

Simplify action attribute update

Under normal circumstances, store , some of which are updated frequently, and each attribute needs action function. When there are more attributes that need to be changed, the amount of code store , Readability will also be reduced. Just like the following code:

class TestStore {
  @observable info = {} as IInfo;
  
  @observable list = [] as IList;
  
  @action
  setInfo = (value: IInfo) => {
    this.info = value;
  }
  
  @action
  setList = (value: IList) => {
    this.list = value;
  }
}

Introducing typescript in keyof keywords, the above may be action function reduces to the following:

class TestStore {
  @observable info = {} as IInfo;
  
  @observable list = [] as IList;
  
  @action
  setValue = <T extends keyof TestStore>(key: T, value: this[T]) => {
    this[key] = value;
  }
}

Simplify related dependencies between stores

Callback realizes the communication between Stores

For example, after a method in StoreA is executed, a method in StoreB needs to be called

// /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(),
}

Page call

// 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 realizes the communication between Stores

// /stores/StoreA.ts
class StoreA {
  @action
  methodA = () => {
    return new Promise((resolve) => {
      // coding...
      resolve();
    })
  }
}

Page call

const Main = (props: IProps) => {
  const { storeA, StoreB } = props;
  
  const { methodA } = storeA;
  
  const { methodB } = storeB;
  
  const handleClick = () => {
    methodA().then(() => {
      methodB();
    });
  }

  return <span onClick={handleClick}></span>
}

Scheduling child stores through the root store to achieve communication

image.png
Introduce the root-level store, and change the above store organization to the following form:

// /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(),
}

Page call

const Main = (props: IProps) => {
  const { storeA, StoreB } = props;
  
  const { methodA } = storeA;
  
  const { methodB } = storeB;
  
  const handleClick = () => {
    methodA();
  }

  return <span onClick={handleClick}></span>
}  

Reduce the granularity of the store

image.png
The business logic and interactions of some project pages are extremely complicated. If these business logics are stacked in a store, the code amount of the store will be extremely large, as shown in the figure above, the store has thousands of lines of code. This will seriously reduce the readability of the code, and it will even affect the development efficiency of future generations if you continue to iterate.

Of course, we can split the above into multiple stores to solve the problem. This scenario is not what I consider in this section. I want to talk about the following scenario:

image.png

If we want to make such a table, and the data structure given by the back end is like this:

image.png

Each object in the quote array corresponds to each quote entry

image.png

If the data of each quotation item needs to be changed, you need to traverse the quote array to find the corresponding quotation item object, re-assign the value, and just write a function. What if the business logic (validation, value change, etc.) related to the quotation item is particularly large? Then you have to write a lot of functions to implement, these business codes related to quotation items are piled in a store will definitely make the store more bloated.

Surely some students will say, isn't it enough to split this part into a separate store? But the tabular data as a whole, this kind of business split is not easy to achieve, so is there any other way?

Certainly, every quotation item object in mobx is an observable object. We can extract this object and put it in another store. The previous store is just a reference, and the description may not be clear. The above code explains:

// 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);
      }
    });
  };
}

Such a design store the organization can be more flexible control store particle size, but also good to avoid store great technology and people operating the same store scene. For example, in the figure, the "form part" can be split into "requirements part" and "quotation part". When multiple people develop at the same time, each person only needs to be responsible for the style, business logic, and data storage in their own modules. To a certain extent, a closed loop is formed, which is beneficial for every development, and such a way of organizing the code will also enhance the readability and reusability of the code, and facilitate subsequent maintenance.


记得要微笑
1.9k 声望4.5k 粉丝

知不足而奋进,望远山而前行,卯足劲,不减热爱。


引用和评论

0 条评论