需求概述
在旧项目中,有一个策略页面包含四种策略,分别为:Auto、Spot、Long 和 Short。页面中涉及多种配置(Config),包括公共配置(Common Config)、期货配置(Futures Config)以及仅适用于现货的配置(Spot Only Config)。
旧项目实现方式
旧项目采用 MVC 架构,页面数据全部存储在 Controller 中。四种策略共用同一个 config。在页面中使用 panel 时,整个 Controller 会被直接传入 props。由于 panel 是一个独立的组件,需要进行数据分离,这种实现方式导致策略页面运行非常卡顿。具体问题包括:每个 panel 都复制了一份完整的数据;当数据发生修改时,所有 panel 都会重新渲染(rerender),用户体验极差。
旧项目里面有一个策略页面, 里面假设有四种策略, 分别为: Auto
, Spot
, Long
, Short
. 下面有一些 Config, 他们有的是公共 Config, 有的是 Futures Config,还有的是 Spot Only Config.
新项目实现方式

- 配置分离:为四种策略分别设置独立的 config。对于公共配置(Common Config),在更新时会同步更新其他三个 config。(为何不单独设置一个 common config?一方面,四种策略的配置已完全分离,公共配置数量较少时,这种方式是可接受的;另一方面,产品需求变动频繁,单独的公共配置不利于后续扩展。)
- Panel 交互优化:panel 组件通过 onChange 回调管理当前页面的数据变动,而 visible 状态则由 Global Store 统一管理,因为这部分与页面无关。
优点:
- 结构清晰:各 panel 之间的数据实现隔离,互不影响,避免了旧项目中数据共享导致的混乱问题。
- 性能提升:单个 config 的变更不会触发其他 panel 的重新渲染(rerender),显著提高页面性能。
- 扩展性强:面对产品需求的变动,只需修改对应的 config,即可快速适应调整。
伪代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| const Page = () => { const { commonVisible, futuresVisible, autoVisible, setCommonVisible, setAutoVisible, setFuturesVisible, } = useGlobalStore()
const [strategyType, setStrategyType] = useState< "Auto", "Long", "Spot", "Short" >("Auto")
const [autoConfig, setAutoConfig] = useState({ }) const [spotConfig, setSpotConfig] = useState({ }) const [longConfig, setLongConfig] = useState({ }) const [shortConfig, setShortConfig] = useState({ })
const onAutoConfigChange = (value) => { setAutoConfig({ ...autoConfig, value }) }
const onCommonConfigChange = (value) => { setAutoConfig({ ...autoConfig, value }) setSpotConfig({ ...spotConfig, value }) setLongConfig({ ...longConfig, value }) setShortConfig({ ...shortConfig, value }) }
const onFuturesConfigChange = (value) => { setLongConfig({ ...longConfig, value }) setShortConfig({ ...shortConfig, value }) }
return ( <div> {/* Change Strategy Type */} <div> <div onClick={() => setStrategyType("Auto")}>Auto</div> <div onClick={() => setStrategyType("Long")}>Long</div> <div onClick={() => setStrategyType("Short")}>Short</div> <div onClick={() => setStrategyType("Spot")}>Spot</div> </div>
<div> {/* Open Config Panel */} <div onClick={() => setCommonVisible(true)}>Common Config</div> {(strategyType === "Long" || strategyType === "Short") && ( <div onClick={() => setFuturesVisible(true)}>Futures Config</div> )} {strategyType === "Auto" && ( <div onClick={() => setAutoVisible(true)}>Auto Config</div> )} </div>
<Panel visible={commonVisible} title="Common" value={autoConfig.value} onChange={onCommonConfigChange} /> <Panel visible={autoVisible} title="Auto" value={autoConfig.value} onChange={onAutoConfigChange} /> <Panel visible={futuresVisible} title="Futures" value={longConfig.value} onChange={onFuturesConfigChange} /> </div> ) }
|