<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>状态管理工程化 on Last Stand</title><link>https://amatsuzero.github.io/LastStand/tags/%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E5%B7%A5%E7%A8%8B%E5%8C%96/</link><description>Recent content in 状态管理工程化 on Last Stand</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Thu, 23 Oct 2025 00:00:00 +0800</lastBuildDate><atom:link href="https://amatsuzero.github.io/LastStand/tags/%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E5%B7%A5%E7%A8%8B%E5%8C%96/index.xml" rel="self" type="application/rss+xml"/><item><title>状态管理工程化</title><link>https://amatsuzero.github.io/LastStand/posts/frontend/engineering/engineering-014/</link><pubDate>Thu, 07 Aug 2025 00:00:00 +0800</pubDate><guid>https://amatsuzero.github.io/LastStand/posts/frontend/engineering/engineering-014/</guid><description>&lt;blockquote&gt;
&lt;p&gt;状态管理是一个前端界老生常谈的话题了，所有前端框架的发展历程中都离不开状态管理的迭代与更替，对于react来说呢，整个状态管理的发展也随着react架构的变更和新特性的加入而不停的做调整，作为一个一起伴随react成长了快5年的开发者，经历过reflux、redux、mobx，以及其他redux衍生方案dva、mirror、rematch等等后，我觉得它们都不是我想要的状态管理的终极形态，所以为了打造一个和react结合得最优雅、使用起来最简单、运行起来最高效的状态管理方案，踏上了追梦旅途。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="为何需要状态管理"&gt;为何需要状态管理&lt;/h2&gt;
&lt;p&gt;为何需要在前端引用里引入状态管理，基本上大家都达成了共识，在此我总结为3点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;随着应用的规模越来越大，功能越来越复杂，组件的抽象粒度会越来越细，在视图中组合起来后层级也会越来越深，能够方便的&lt;strong&gt;跨组件共享状态&lt;/strong&gt;成为迫切的需求。&lt;/li&gt;
&lt;li&gt;状态也需要按模块切分，状态的变更逻辑背后其实就是我们的业务逻辑，将其抽离出来能够彻底&lt;strong&gt;解耦ui和业务&lt;/strong&gt;，有利于逻辑复用，以及持续的维护和迭代。&lt;/li&gt;
&lt;li&gt;状态如果能够被集中的管理起来，并合理的派发有利于组件&lt;strong&gt;按需更新&lt;/strong&gt;，缩小渲染范围，从而提高渲染性能&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="已有状态管理方案现状"&gt;已有状态管理方案现状&lt;/h2&gt;
&lt;h3 id="redux"&gt;redux&lt;/h3&gt;
&lt;p&gt;遵循react不可变思路的状态管理方案，无论从git的star排名还是社区的繁荣度，首推的一定是&lt;code&gt;redux&lt;/code&gt;这个react界状态管理一哥，约束使用唯一路径&lt;code&gt;reducer&lt;/code&gt;纯函数去修改store的数据，从而达到整个应用的状态流转清晰、可追溯。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/engineering/engineering-014/image-01.png"&gt;&lt;/p&gt;
&lt;p&gt;image.png&lt;/p&gt;
&lt;h3 id="mbox"&gt;mbox&lt;/h3&gt;
&lt;p&gt;遵循响应式的后期之秀&lt;code&gt;mbox&lt;/code&gt;，提出了&lt;code&gt;computed&lt;/code&gt;、&lt;code&gt;reaction&lt;/code&gt;的概念，其官方的口号就是&lt;strong&gt;任何可以从应用程序状态派生的内容都应该派生出来&lt;/strong&gt;，通过将原始的普通json对象转变为可观察对象，我们可以直接修改状态，&lt;code&gt;mbox&lt;/code&gt;会自动驱动ui渲染更新，因其响应式的理念和&lt;code&gt;vue&lt;/code&gt;很相近，在&lt;code&gt;react&lt;/code&gt;里搭配&lt;code&gt;mobx-react&lt;/code&gt;使用后，很多人戏称&lt;code&gt;mobx&lt;/code&gt;是一个将&lt;code&gt;react&lt;/code&gt;变成了类&lt;code&gt;vue&lt;/code&gt;开发体验的状态管理方案。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/engineering/engineering-014/image-02.png"&gt;&lt;/p&gt;
&lt;p&gt;image.png&lt;/p&gt;
&lt;p&gt;当然因为&lt;code&gt;mbox&lt;/code&gt;操作数据很方便，不满足大型应用里对状态流转路径清晰可追溯的诉求，为了约束用户的更新行为，配套出了一个&lt;code&gt;mobx-state-tree&lt;/code&gt;，总而言之，&lt;code&gt;mobx&lt;/code&gt;成为了响应式的代表。&lt;/p&gt;
&lt;h3 id="其他"&gt;其他&lt;/h3&gt;
&lt;p&gt;剩下的状态管理方案，主要有3类。&lt;/p&gt;
&lt;p&gt;一类是不满足&lt;code&gt;redux&lt;/code&gt;代码冗余啰嗦，接口不够友好等缺点，进而在&lt;code&gt;redux&lt;/code&gt;之上做2次封装，典型的代表国外的有如&lt;code&gt;rematch&lt;/code&gt;，国内有如&lt;code&gt;dva&lt;/code&gt;、&lt;code&gt;mirror&lt;/code&gt;等，我将它们称为&lt;code&gt;redux&lt;/code&gt;衍生的家族作品，或者是解读了&lt;code&gt;redux&lt;/code&gt;源码，整合自己的思路重新设计一个库，如&lt;code&gt;final-state&lt;/code&gt;、&lt;code&gt;retalk&lt;/code&gt;、&lt;code&gt;hydux&lt;/code&gt;等，我将它们称为类&lt;code&gt;redux&lt;/code&gt;作品。&lt;/p&gt;
&lt;p&gt;一类是走响应式道路的方案，和&lt;code&gt;mobx&lt;/code&gt;一样，劫持普通状态对象转变为可观察对象，如&lt;code&gt;dob&lt;/code&gt;，我将它们称为类&lt;code&gt;mobx&lt;/code&gt;作品。&lt;/p&gt;
&lt;p&gt;剩下的就是利用&lt;code&gt;react context api&lt;/code&gt;或者最新的&lt;code&gt;hook&lt;/code&gt;特性，主打轻量，上手简单，概念少的方案，如&lt;code&gt;unstated-next&lt;/code&gt;，&lt;code&gt;reactn&lt;/code&gt;、&lt;code&gt;smox&lt;/code&gt;、&lt;code&gt;react-model&lt;/code&gt;等。&lt;/p&gt;
&lt;h2 id="我心中的理想方案"&gt;我心中的理想方案&lt;/h2&gt;
&lt;p&gt;上述相关的各种方案，都各自在一定程度上能满足我们的需求，但是对于追求完美的水瓶座程序猿，我觉得它们终究都不是我理想的方案，它们或小而美、或大而全，但还是不够强，不够友好，所以决定开始自研状态管理方案。&lt;/p&gt;
&lt;p&gt;我知道小和 美、全、强本身是相冲突的，我能接受一定量的大，gzip后10kb到20kb都是我接受的范围，在此基础上，去逐步地实现美、全、强，以便达到以下目的，从而体现出和现有状态管理框架的差异性、优越性。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;让新手使用的时候，无需了解新的特性api，无感知状态管理的存在，使其遁于无形之中，仅按照react的思路组织代码，就能享受到状态管理带来的福利。&lt;/li&gt;
&lt;li&gt;让老手可以结合对状态管理的已有认知来使用新提供的特性api，还原各种社区公认的最佳实践，同时还能向上继续探索和提炼，挖掘状态管理带来的更多收益。&lt;/li&gt;
&lt;li&gt;在&lt;code&gt;react&lt;/code&gt;有了&lt;code&gt;hook&lt;/code&gt;特性之后，让class组件和function组件都能够享有一致的思路、一致的api接入状态管理，不产生割裂感。&lt;/li&gt;
&lt;li&gt;在保持以上3点的基础上，让用户能够使用更精简且更符合思维直觉的组织方式书写代码，同时还能够获得巨大的性能提升收益。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了达成以上目标，立项&lt;code&gt;concent&lt;/code&gt;，将其定义为一个&lt;strong&gt;可预测、零入侵、渐进式、高性能的增强型状态管理方案&lt;/strong&gt;，期待能把他打磨成为一个真真实实让用户用起来感觉到美丽、全面、强大的框架。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;说人话就是：理解起来够简单、代码写起来够优雅、工程架构起来够健壮、性能用起来够卓越&amp;hellip;&amp;hellip; ^_^&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/engineering/engineering-014/image-03.png"&gt;&lt;/p&gt;
&lt;p&gt;concent.png&lt;/p&gt;
&lt;h3 id="可预测"&gt;可预测&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;react&lt;/code&gt;是一个基于&lt;code&gt;pull based&lt;/code&gt;来做变化侦测的ui框架，对于用户来说，需要显式的调用&lt;code&gt;setState&lt;/code&gt;来让&lt;code&gt;react&lt;/code&gt;感知到状态变化，所以&lt;code&gt;concent&lt;/code&gt;遵循react经典的不可变原则来体现可预测，不使用劫持对象将转变为可观察对象的方式来感知状态变化（要不然又成为了一个类&lt;code&gt;mobx&lt;/code&gt;&amp;hellip;&amp;hellip;）, 也不使用时全局&lt;code&gt;pub&amp;amp;sub&lt;/code&gt;的模式来驱动相关视图更新，同时还要配置各种&lt;code&gt;reselect&lt;/code&gt;、&lt;code&gt;redux-saga&lt;/code&gt;等&lt;a href="https://cloud.tencent.com/product/message-queue-catalog?from_column=20065&amp;amp;from=20065"&gt;中间件&lt;/a&gt;来解决计算缓存、异步action等等问题（如果这样，岂不是又迈向了一个redux全家桶轮子的不归路&amp;hellip;.. ）&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;吐槽一下：redux粗放的订阅粒度在组件越来越多，状态越来越复杂的时候，经常因为组件订阅了不需要的数据而造成冗余更新，而且各种手写mapXXXToYYY很烦啊有木有啊有木有，伤不起啊伤不起&amp;hellip;&amp;hellip;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="零入侵"&gt;零入侵&lt;/h3&gt;
&lt;p&gt;上面提到了期望新手仅按照react的思路组织代码，就能够享受到状态管理带来的福利，所以必然只能在&lt;code&gt;setState&lt;/code&gt;之上做文章，其实我们可以把&lt;code&gt;setState&lt;/code&gt;当做一个下达渲染指令重要入口（除此之外，还有&lt;code&gt;forceUpdate&lt;/code&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;img loading="lazy" src="https://amatsuzero.github.io/LastStand/posts/frontend/engineering/engineering-014/image-04.png"&gt;&lt;/p&gt;
&lt;p&gt;setState，下达更新指令&lt;/p&gt;
&lt;p&gt;仔细看看上图，有没有发现有什么描述不太准确的地方，我们看看官方的&lt;code&gt;setState&lt;/code&gt;函数签名描述:&lt;/p&gt;
&lt;p&gt;代码语言：txt&lt;/p&gt;
&lt;p&gt;AI代码解释&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;setState&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;K &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; keyof S&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; state: ((prevState: Readonly&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;S&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;, props: Readonly&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;P&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;) &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; (Pick&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;S, K&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; S &lt;span style="color:#f92672"&gt;|&lt;/span&gt; null)) &lt;span style="color:#f92672"&gt;|&lt;/span&gt; (Pick&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;S, K&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; &lt;span style="color:#f92672"&gt;|&lt;/span&gt; S &lt;span style="color:#f92672"&gt;|&lt;/span&gt; null),
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; callback&lt;span style="color:#960050;background-color:#1e0010"&gt;?&lt;/span&gt;: () &lt;span style="color:#f92672"&gt;=&amp;gt;&lt;/span&gt; void
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;): void;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过签名描述，我们可以看出传递给&lt;code&gt;setState&lt;/code&gt;的是一个部分状态(片段状态)，实际上我们在调用&lt;code&gt;setState&lt;/code&gt;也是经常这么做的，修改了谁就传递对应的&lt;code&gt;stateKey&lt;/code&gt;和值。&lt;/p&gt;</description></item></channel></rss>