<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Angular状态管理深度探索 on 雪狼的书斋</title>
    <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/</link>
    <description>Recent content in Angular状态管理深度探索 on 雪狼的书斋</description>
    <generator>Hugo</generator>
    <language>zh-hans</language>
    <atom:link href="/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>1.告别“状态焦虑”：Angular状态管理，你选对了吗？</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/010-%E5%91%8A%E5%88%AB%E7%8A%B6%E6%80%81%E7%84%A6%E8%99%91angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%BD%A0%E9%80%89%E5%AF%B9%E4%BA%86%E5%90%97/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/010-%E5%91%8A%E5%88%AB%E7%8A%B6%E6%80%81%E7%84%A6%E8%99%91angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%BD%A0%E9%80%89%E5%AF%B9%E4%BA%86%E5%90%97/</guid>
      <description>&lt;blockquote class=&#39;book-hint &#39;&gt;&#xA;&lt;p&gt;「这个按钮的 &lt;code&gt;disabled&lt;/code&gt; 状态由谁决定？」&lt;/p&gt;&#xA;&lt;p&gt;「用户登录后，头像和昵称怎么通知到 Header 组件？」&lt;/p&gt;&#xA;&lt;p&gt;「这个列表筛选条件，我跳到别的页面再回来，怎么就没了？」&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;是不是很熟悉的场景？这些问题，都指向了前端开发中最核心、也最令人头疼的难题 —— &lt;strong&gt;状态管理&lt;/strong&gt;。当你的应用逐渐庞大，数据就像一群没有牧羊人的羊，四处乱窜、随时可能丢失、甚至被不知名的野狼（Bug）叼走。这种失控感，我称之为「&lt;strong&gt;状态焦虑&lt;/strong&gt;」 。&lt;/p&gt;&#xA;&lt;p&gt;「状态焦虑」的根源，并非 Angular 不够强大，而是我们常常试图用一种「万金油」方案去解决所有问题，或者干脆「随心而行」，导致应用最终变成一团乱麻。&lt;/p&gt;&#xA;&lt;p&gt;今天，雪狼不给你推销任何一个特定的状态管理库，而是想为你提供一张「地图」，让你看清状态管理的「全貌光谱」，并学会如何「对症下药」，为你的应用选择最合适的「定心丸」。&lt;/p&gt;&#xA;&lt;h2 id=&#34;首先什么是状态&#34;&gt;首先，什么是「状态」？&lt;a class=&#34;anchor&#34; href=&#34;#%e9%a6%96%e5%85%88%e4%bb%80%e4%b9%88%e6%98%af%e7%8a%b6%e6%80%81&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;广义上讲，任何随时间变化的数据，都是状态。我们可以粗略地把它分为两类：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;服务器状态 (Server State)&lt;/strong&gt;：这些数据的老家在后端，前端只是它的「镜像」。比如商品列表、用户信息等。我们关心的是如何获取、缓存以及与后端同步。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;客户端状态 (Client State)&lt;/strong&gt;：这些数据只活在前端。比如「暗黑模式」的开关、一个 Modal 是否被打开、一个表单里用户正在输入的内容。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;而状态管理的「焦虑」，正是源于我们如何组织、修改和共享这些五花八门的数据。&lt;/p&gt;&#xA;&lt;h2 id=&#34;状态管理的光谱从个人心念到中央银行&#34;&gt;状态管理的「光谱」：从「个人心念」到「中央银行」&lt;a class=&#34;anchor&#34; href=&#34;#%e7%8a%b6%e6%80%81%e7%ae%a1%e7%90%86%e7%9a%84%e5%85%89%e8%b0%b1%e4%bb%8e%e4%b8%aa%e4%ba%ba%e5%bf%83%e5%bf%b5%e5%88%b0%e4%b8%ad%e5%a4%ae%e9%93%b6%e8%a1%8c&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;请记住，状态管理不是一个「是」或「否」要用 NgRx 的问题。它是一个「光谱」，你需要根据问题的规模，选择对应的解决方案。&lt;/p&gt;&#xA;&lt;h3 id=&#34;光谱零signal--个人的心念&#34;&gt;光谱零：&lt;code&gt;signal()&lt;/code&gt; —— 「个人的心念」&lt;a class=&#34;anchor&#34; href=&#34;#%e5%85%89%e8%b0%b1%e9%9b%b6signal--%e4%b8%aa%e4%ba%ba%e7%9a%84%e5%bf%83%e5%bf%b5&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：一个组件&lt;strong&gt;内部&lt;/strong&gt;的、私有的状态。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：&lt;code&gt;signal()&lt;/code&gt; 和 &lt;code&gt;computed()&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;心智模型&lt;/strong&gt;：就像你自己的「念头」。一个按钮是否 &lt;code&gt;disabled&lt;/code&gt;，一个下拉菜单是否展开，这些都只跟你自己有关，无需告诉任何人。这是最轻量、最高效、也是&lt;strong&gt;现代 Angular 首选&lt;/strong&gt;的组件内部状态管理方式。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;光谱一inputoutput--家庭内部会议&#34;&gt;光谱一：&lt;code&gt;@Input&lt;/code&gt;/&lt;code&gt;@Output&lt;/code&gt; —— 「家庭内部会议」&lt;a class=&#34;anchor&#34; href=&#34;#%e5%85%89%e8%b0%b1%e4%b8%80inputoutput--%e5%ae%b6%e5%ba%ad%e5%86%85%e9%83%a8%e4%bc%9a%e8%ae%ae&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：最简单的&lt;strong&gt;父子组件&lt;/strong&gt;关系。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：&lt;code&gt;input()&lt;/code&gt; 函数 (&lt;code&gt;@Input&lt;/code&gt;) 和 &lt;code&gt;@Output()&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;心智模型&lt;/strong&gt;：就像开「家庭会议」。父亲（父组件）通过 &lt;code&gt;@Input&lt;/code&gt; 给孩子（子组件）零花钱和指示，孩子通过 &lt;code&gt;@Output&lt;/code&gt; 向父亲报告考试成绩。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;光谱二共享服务--村里的公告栏&#34;&gt;光谱二：共享服务 —— 「村里的公告栏」&lt;a class=&#34;anchor&#34; href=&#34;#%e5%85%89%e8%b0%b1%e4%ba%8c%e5%85%b1%e4%ba%ab%e6%9c%8d%e5%8a%a1--%e6%9d%91%e9%87%8c%e7%9a%84%e5%85%ac%e5%91%8a%e6%a0%8f&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：&lt;strong&gt;兄弟组件、叔侄组件&lt;/strong&gt;等非直接父子关系，但又同属于一个「村落」（功能模块）的组件间通信。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;解决方案&lt;/strong&gt;：一个注入在他们共同祖先上的服务，内部使用 &lt;code&gt;signal&lt;/code&gt; 或 &lt;code&gt;BehaviorSubject&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;心智模型&lt;/strong&gt;：服务就是「村里的公告栏」。A 家（组件 A）有喜事了，就去公告栏上更新一下信息（调用服务的 &lt;code&gt;update&lt;/code&gt; 方法），全村（所有注入了该服务的组件）就都看到了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h3 id=&#34;光谱三组件状态管理-component-store--部门内部账本&#34;&gt;光谱三：组件状态管理 (Component Store) —— 「部门内部账本」&lt;a class=&#34;anchor&#34; href=&#34;#%e5%85%89%e8%b0%b1%e4%b8%89%e7%bb%84%e4%bb%b6%e7%8a%b6%e6%80%81%e7%ae%a1%e7%90%86-component-store--%e9%83%a8%e9%97%a8%e5%86%85%e9%83%a8%e8%b4%a6%e6%9c%ac&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;适用场景&lt;/strong&gt;：某个&lt;strong&gt;复杂特性&lt;/strong&gt;自身内部的状态管理。&lt;/p&gt;</description>
    </item>
    <item>
      <title>2.RxJS BehaviorSubject：Angular中“大道至简”的状态管理之道</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/020-rxjs-behaviorsubjectangular%E4%B8%AD%E5%A4%A7%E9%81%93%E8%87%B3%E7%AE%80%E7%9A%84%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%B9%8B%E9%81%93/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/020-rxjs-behaviorsubjectangular%E4%B8%AD%E5%A4%A7%E9%81%93%E8%87%B3%E7%AE%80%E7%9A%84%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%B9%8B%E9%81%93/</guid>
      <description>&lt;p&gt;一提到 Angular 状态管理，很多人的第一反应就是：「上 NgRx！」。于是，Action, Reducer, Effect, Selector 等一堆新概念扑面而来，学习曲线陡峭，样板代码繁多，让人望而生畏。仿佛要管理好几个组件间的状态，就必须动用「国家中央银行」级别的武器。&lt;/p&gt;&#xA;&lt;p&gt;但，杀鸡焉用牛刀？&lt;/p&gt;&#xA;&lt;p&gt;今天，雪狼想告诉你一个秘密：在 Angular 的世界里，状态管理的「大道至简」之道，就藏在你最熟悉的工具里。在过去，这件神兵是 RxJS 的 &lt;code&gt;BehaviorSubject&lt;/code&gt;；在今天，我们又多了一条更直接的「阳光大道」 —— &lt;code&gt;signal&lt;/code&gt;。让我们来看看，这两条路，分别通往怎样的风景。&lt;/p&gt;&#xA;&lt;h2 id=&#34;问题的根源为何不能只用一个普通变量&#34;&gt;问题的根源：为何不能只用一个普通变量？&lt;a class=&#34;anchor&#34; href=&#34;#%e9%97%ae%e9%a2%98%e7%9a%84%e6%a0%b9%e6%ba%90%e4%b8%ba%e4%bd%95%e4%b8%8d%e8%83%bd%e5%8f%aa%e7%94%a8%e4%b8%80%e4%b8%aa%e6%99%ae%e9%80%9a%e5%8f%98%e9%87%8f&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;一个天真的想法：我为什么不能在服务里只用一个普通属性来共享状态呢？&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// NaiveService.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@Injectable&lt;/span&gt;({&lt;span style=&#34;color:#a6e22e&#34;&gt;providedIn&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;NaiveService&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;sharedState&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;初始状态&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;问题在于「&lt;strong&gt;时间&lt;/strong&gt;」 。组件 A 在某个时刻更新了 &lt;code&gt;sharedState&lt;/code&gt;，组件 B 如何&lt;strong&gt;得知&lt;/strong&gt;这个变化？它总不能用一个 &lt;code&gt;setInterval&lt;/code&gt; 每100毫秒就去检查一遍吧？我们需要一种机制，当状态变化时，能&lt;strong&gt;主动通知&lt;/strong&gt;所有关心它的「人」。&lt;/p&gt;&#xA;&lt;h2 id=&#34;经典解法rxjs-behaviorsubject-的公告板模式&#34;&gt;经典解法：RxJS &lt;code&gt;BehaviorSubject&lt;/code&gt; 的「公告板」模式&lt;a class=&#34;anchor&#34; href=&#34;#%e7%bb%8f%e5%85%b8%e8%a7%a3%e6%b3%95rxjs-behaviorsubject-%e7%9a%84%e5%85%ac%e5%91%8a%e6%9d%bf%e6%a8%a1%e5%bc%8f&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;code&gt;BehaviorSubject&lt;/code&gt; 就像一个带「显示屏」的公告板。它永远会记住&lt;strong&gt;最近一次&lt;/strong&gt;的公告，并要求必须有一个&lt;strong&gt;初始值&lt;/strong&gt;。这完美地解决了普通变量的「时间」问题。&lt;/p&gt;&#xA;&lt;p&gt;我们可以用它来打造一个「简易店铺」。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// user-state.rxjs.service.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@Injectable&lt;/span&gt;({&lt;span style=&#34;color:#a6e22e&#34;&gt;providedIn&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;UserStateRxjsService&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 「私有仓库」：用 BehaviorSubject 来存放我们的「货」（状态）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;userSource&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BehaviorSubject&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;User&lt;/span&gt; &lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;null&lt;/span&gt;&amp;gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 「公开展柜」：把仓库里的货，通过一个只读的 Observable 管道暴露出去&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;user$&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;userSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;asObservable&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 「收银台/入库口」：提供明确的、唯一的入口来修改「库存」&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;login&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;User&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;userSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;next&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;消费方式：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// profile.component.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@Component&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;standalone&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;imports&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&lt;span style=&#34;color:#a6e22e&#34;&gt;AsyncPipe&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;template&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    @if (user$ | async; as user) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;lt;h1&amp;gt;欢迎, {{ user.name }}&amp;lt;/h1&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    } @else {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;lt;p&amp;gt;请登录&amp;lt;/p&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  `&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ProfileComponent&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;user$&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;inject&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;UserStateRxjsService&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;user$&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这个模式非常经典，它提供了单一数据源、响应式流和封装好的修改方法。在处理需要与复杂 RxJS 管道（如 &lt;code&gt;debounceTime&lt;/code&gt;, &lt;code&gt;switchMap&lt;/code&gt;）深度集成的状态时，它依然是最佳选择。&lt;/p&gt;</description>
    </item>
    <item>
      <title>3.服务状态管理：Angular组件间“心电感应”的秘密</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/030-%E6%9C%8D%E5%8A%A1%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86angular%E7%BB%84%E4%BB%B6%E9%97%B4%E5%BF%83%E7%94%B5%E6%84%9F%E5%BA%94%E7%9A%84%E7%A7%98%E5%AF%86/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/030-%E6%9C%8D%E5%8A%A1%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86angular%E7%BB%84%E4%BB%B6%E9%97%B4%E5%BF%83%E7%94%B5%E6%84%9F%E5%BA%94%E7%9A%84%E7%A7%98%E5%AF%86/</guid>
      <description>&lt;p&gt;你有没有想过，在 Angular 应用中，一个远在天边（组件树的某个遥远角落）的组件，是如何能「瞬间」感知到另一个组件中发生的变化的？它们之间仿佛有一种「心电感应」。&lt;/p&gt;&#xA;&lt;p&gt;这种「超能力」并非魔法，其秘密就藏在你每天都在使用的 Angular 服务（Service）之中。今天，我们就来揭示，如何将一个平平无奇的服务，修炼成组件间的「共享意识」，让它们无需言语（&lt;code&gt;@Input&lt;/code&gt;/&lt;code&gt;@Output&lt;/code&gt;），即可实现心灵相通。&lt;/p&gt;&#xA;&lt;h2 id=&#34;服务不止是工具箱更是意识容器&#34;&gt;服务：不止是「工具箱」，更是「意识容器」&lt;a class=&#34;anchor&#34; href=&#34;#%e6%9c%8d%e5%8a%a1%e4%b8%8d%e6%ad%a2%e6%98%af%e5%b7%a5%e5%85%b7%e7%ae%b1%e6%9b%b4%e6%98%af%e6%84%8f%e8%af%86%e5%ae%b9%e5%99%a8&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;很多开发者将服务仅仅看作一个「工具箱」，里面放着一些可复用的函数，或者用来调用 HTTP 请求。这没错，但这大大低估了服务的潜力。&lt;/p&gt;&#xA;&lt;p&gt;在 Angular 的架构中，服务最强大的角色，是作为一个&lt;strong&gt;有状态的单例（Stateful Singleton）&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;得益于 Angular 强大的依赖注入体系，一个标记了 &lt;code&gt;providedIn: &#39;root&#39;&lt;/code&gt; 的服务，在整个应用的生命周期中，&lt;strong&gt;只会存在一个实例&lt;/strong&gt;。这个「唯一」的实例，就成了一个所有组件都可以访问的「公共空间」，一个可以承载共享状态的「意识容器」。&lt;/p&gt;&#xA;&lt;h2 id=&#34;心电感应的实现原理&#34;&gt;「心电感应」的实现原理&lt;a class=&#34;anchor&#34; href=&#34;#%e5%bf%83%e7%94%b5%e6%84%9f%e5%ba%94%e7%9a%84%e5%ae%9e%e7%8e%b0%e5%8e%9f%e7%90%86&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;让我们来拆解一下这个「心电感应」的过程：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;组件 A（发送者）&lt;/strong&gt;：它不关心谁会听到它的「心声」。它只是向「共享意识」（服务）发出一个念头。比如，调用 &lt;code&gt;authService.login(user)&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;服务（共享意识）&lt;/strong&gt;：它接收到这个「念头」，并更新自己内部维护的状态。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;组件 B（接收者）&lt;/strong&gt;：它并没有直接「偷听」组件 A。它只是持续地与「共享意识」保持连接。当服务中的状态更新时，这个新的「念头」会自动地、响应式地「流入」组件 B 的脑海中。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;img src=&#34;angular_service_state_images/telepathy.jpg&#34; alt=&#34;文生图：抽象概念插画。中间是一个发光的大脑（共享服务）。左边的A组件向大脑发射一道光波（调用方法）。右边的B组件和C组件各自有一条光纤连接到大脑，接收从大脑发出的光波（订阅Observable/Signal）。组件之间没有直接连接。风格：简洁、科技感。&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;这种模式的美妙之处在于&lt;strong&gt;彻底的解耦&lt;/strong&gt;。组件 A 和组件 B 互不知晓对方的存在。&lt;/p&gt;&#xA;&lt;h3 id=&#34;实现方式rxjs-的水之道-vs-signal-的光之道&#34;&gt;实现方式：RxJS 的「水之道」 vs. Signal 的「光之道」&lt;a class=&#34;anchor&#34; href=&#34;#%e5%ae%9e%e7%8e%b0%e6%96%b9%e5%bc%8frxjs-%e7%9a%84%e6%b0%b4%e4%b9%8b%e9%81%93-vs-signal-%e7%9a%84%e5%85%89%e4%b9%8b%e9%81%93&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;这个「共享意识」内部，可以由 RxJS 构建，也可以由 Signal 构建。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;方案 A (RxJS - 水之道):&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@Injectable&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;providedIn&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt; })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RxjsStateService&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BehaviorSubject&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;message&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;&amp;#39;&lt;/span&gt; });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;state$&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;asObservable&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;updateMessage&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;msg&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;) { &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;next&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;message&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;msg&lt;/span&gt; }); }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 消费方组件： user$ = inject(RxjsStateService).state$;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 模板： @if(user$ | async; as user) { ... }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;方案 B (Signal - 光之道):&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>4.Angular Signals：响应式编程的“新纪元”，告别Zone.js的“烦恼”？</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/040-angular-signals%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B%E7%9A%84%E6%96%B0%E7%BA%AA%E5%85%83%E5%91%8A%E5%88%ABzone.js%E7%9A%84%E7%83%A6%E6%81%BC/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/040-angular-signals%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B%E7%9A%84%E6%96%B0%E7%BA%AA%E5%85%83%E5%91%8A%E5%88%ABzone.js%E7%9A%84%E7%83%A6%E6%81%BC/</guid>
      <description>&lt;p&gt;多年以来，Angular 的响应式体系，一直由一位强大、神秘、却又时常引发「烦恼」的「幕后功臣」所驱动 —— 它就是 &lt;code&gt;Zone.js&lt;/code&gt;。它就像一张「天罗地网」，自动捕获所有异步事件，并触发变更检测。这很「魔法」，但有时，也是「黑魔法」的源头（&lt;code&gt;ExpressionChangedAfterItHasBeenCheckedError&lt;/code&gt;，性能问题等）。&lt;/p&gt;&#xA;&lt;p&gt;现在，一个全新的「门派」崛起了。它光明正大，无需「魔法」，讲究的是「精准打击」，而非「地毯式轰炸」。它，就是 &lt;strong&gt;Angular Signals&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;Signals 的到来，不亚于 Angular 内部的一场「心脏手术」。它预示着一个更简单、更高效、甚至最终可能「告别 Zone.js」的「新纪元」的开启。&lt;/p&gt;&#xA;&lt;h2 id=&#34;旧时代的回响zonejs-的天罗地网&#34;&gt;旧时代的回响：Zone.js 的「天罗地网」&lt;a class=&#34;anchor&#34; href=&#34;#%e6%97%a7%e6%97%b6%e4%bb%a3%e7%9a%84%e5%9b%9e%e5%93%8dzonejs-%e7%9a%84%e5%a4%a9%e7%bd%97%e5%9c%b0%e7%bd%91&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;简单回顾一下，&lt;code&gt;Zone.js&lt;/code&gt; 的工作模式是「全局广播」：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;它像一个「村口大喇叭」，任何异步事件（点击、&lt;code&gt;setTimeout&lt;/code&gt; 等）一发生，它就向全村（整个应用）广播：「有情况了，大家注意！」&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;听到广播后，Angular 会启动一轮从上到下的、地毯式的变更检测，检查每一个组件，看看有谁需要更新。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;优点&lt;/strong&gt;：开发者体验好，你只需改变一个属性，UI 「自动」就更新了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;烦恼&lt;/strong&gt;：效率低下，很多「没情况」的组件也被迫接受检查；同时，这套「魔法」也带来了 &lt;code&gt;ExpressionChangedAfterItHasBeenCheckedError&lt;/code&gt; 等难以理解的「诅咒」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;新纪元的主角signals-的点对点私信&#34;&gt;新纪元的主角：Signals 的「点对点私信」&lt;a class=&#34;anchor&#34; href=&#34;#%e6%96%b0%e7%ba%aa%e5%85%83%e7%9a%84%e4%b8%bb%e8%a7%92signals-%e7%9a%84%e7%82%b9%e5%af%b9%e7%82%b9%e7%a7%81%e4%bf%a1&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Signal 是一种全新的响应式基础原语。它的核心思想，彻底颠覆了 Zone.js 的模式。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;如果说 Zone.js 是「村口大喇叭」，那么 Signal 就是一个「点对点的私信系统」。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;angular_signals_images/signal_vs_zone.jpg&#34; alt=&#34;文生图：概念插画。左边是Zone.js的“大喇叭”模式，一个大喇叭向全城广播，所有人都被迫在听。右边是Signals的“私信”模式，一个数据源（Signal）精准地向几个特定的订阅者（组件）发送私信，其他人不受打扰。&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;它的工作流程如下：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;signal(initialValue)&lt;/code&gt;&lt;/strong&gt;：创建一个 &lt;code&gt;signal&lt;/code&gt;，就像创建了一个「私密聊天群」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;mySignal()&lt;/code&gt;&lt;/strong&gt;：在模板或 &lt;code&gt;computed&lt;/code&gt; 中「读取」一个 &lt;code&gt;signal&lt;/code&gt; 的值。这个动作，就像是你加入了这个聊天群，自动完成了「订阅」。Signal 会默默记下：「哦，这个组件对我的值感兴趣。」&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;&lt;code&gt;.set(newValue)&lt;/code&gt; 或 &lt;code&gt;.update(fn)&lt;/code&gt;&lt;/strong&gt;：修改 &lt;code&gt;signal&lt;/code&gt; 的值。这就像你在聊天群里发了一条新消息。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;精准通知&lt;/strong&gt;：Signal 会立即翻阅它的「订阅者列表」，然后&lt;strong&gt;只&lt;/strong&gt;向那些真正关心它变化的组件发送「私信」：「我变了，你该更新了！」&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;这个过程里，没有全局广播，没有从上到下的遍历，只有高效、精准的「点对点」通知。&lt;/p&gt;&#xA;&lt;h2 id=&#34;signal-的三板斧signal-computed-effect&#34;&gt;Signal 的「三板斧」：&lt;code&gt;signal&lt;/code&gt;, &lt;code&gt;computed&lt;/code&gt;, &lt;code&gt;effect&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#signal-%e7%9a%84%e4%b8%89%e6%9d%bf%e6%96%a7signal-computed-effect&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;1-signal你的响应式宝盒&#34;&gt;1. &lt;code&gt;signal&lt;/code&gt;：你的响应式「宝盒」&lt;a class=&#34;anchor&#34; href=&#34;#1-signal%e4%bd%a0%e7%9a%84%e5%93%8d%e5%ba%94%e5%bc%8f%e5%ae%9d%e7%9b%92&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;它是一个包裹着你的值的「宝盒」。你可以 &lt;code&gt;.set()&lt;/code&gt; 一个全新的宝物进去，或者 &lt;code&gt;.update()&lt;/code&gt; 对盒中的宝物进行加工。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;signal&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// 创建一个装着 0 的宝盒&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;set&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;5&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// 放入新宝物 5&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;update&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;currentValue&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;currentValue&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;); &lt;span style=&#34;color:#75715e&#34;&gt;// 加工一下，现在是 6&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;console&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;log&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;count&lt;/span&gt;()); &lt;span style=&#34;color:#75715e&#34;&gt;// 打开宝盒，看看现在是 6&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;2-computed依赖你我的智能合约&#34;&gt;2. &lt;code&gt;computed&lt;/code&gt;：依赖你我的「智能合约」&lt;a class=&#34;anchor&#34; href=&#34;#2-computed%e4%be%9d%e8%b5%96%e4%bd%a0%e6%88%91%e7%9a%84%e6%99%ba%e8%83%bd%e5%90%88%e7%ba%a6&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;&lt;code&gt;computed&lt;/code&gt; 用于创建&lt;strong&gt;派生状态&lt;/strong&gt;。它像一份「智能合约」，能根据其他一个或多个 &lt;code&gt;signal&lt;/code&gt; 的值，自动计算出自己的值。&lt;/p&gt;</description>
    </item>
    <item>
      <title>5.NgRx Alternatives：Angular生态中的“百家争鸣”，谁主沉浮？</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/050-ngrx-alternativesangular%E7%94%9F%E6%80%81%E4%B8%AD%E7%9A%84%E7%99%BE%E5%AE%B6%E4%BA%89%E9%B8%A3%E8%B0%81%E4%B8%BB%E6%B2%89%E6%B5%AE/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/050-ngrx-alternativesangular%E7%94%9F%E6%80%81%E4%B8%AD%E7%9A%84%E7%99%BE%E5%AE%B6%E4%BA%89%E9%B8%A3%E8%B0%81%E4%B8%BB%E6%B2%89%E6%B5%AE/</guid>
      <description>&lt;p&gt;曾几何时，提及 Angular 的全局状态管理，NgRx 就像是「武林盟主」，是那座不可逾越的「少林寺」。它源自 Redux，内功深厚（纯函数、不可变性），戒律森严（Action, Reducer, Effect），为大型企业级应用带来了前所未有的可预测性与稳定性。&lt;/p&gt;&#xA;&lt;p&gt;但，江湖永远不会只有一个声音。随着时间的推移，各大门派高手辈出，他们或另辟蹊径，或化繁为简，形成了一场精彩纷呈的「百家争鸣」。今天，雪狼就为你摆下这场「英雄宴」，带你领略除了 NgRx 这位「盟主」之外，Angular 状态管理江湖中的各路豪杰。&lt;/p&gt;&#xA;&lt;h2 id=&#34;名门正派少林ngrx&#34;&gt;名门正派「少林」：NgRx&lt;a class=&#34;anchor&#34; href=&#34;#%e5%90%8d%e9%97%a8%e6%ad%a3%e6%b4%be%e5%b0%91%e6%9e%97ngrx&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;武功心法&lt;/strong&gt;：师从 Redux，信奉「纯函数」与「不可变性」的函数式编程正道。所有内力（状态）变更，都必须遵循「打报告（Action）-&amp;gt; 批条子（Reducer）-&amp;gt; 办事情（Effect）」的严格流程。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;独门绝技&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;时光倒流（Time-travel Debugging）&lt;/strong&gt;：得益于其严格的流程，配合 Redux DevTools，你可以像播放录像带一样，回溯每一次状态变更，堪称调试「神器」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;生态宏大&lt;/strong&gt;：&lt;code&gt;@ngrx/entity&lt;/code&gt; 管理范式化数据，&lt;code&gt;@ngrx/data&lt;/code&gt; 零代码处理 CRUD，各种周边秘籍应有尽有。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;修行门槛&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;「仪式感」太重&lt;/strong&gt;：哪怕只是想改一个最简单的状态，也得先把「报告、条子、办事员」一整套班子搭起来。样板代码（Boilerplate）多，劝退不少新手。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;内功要求高&lt;/strong&gt;：需要对 Redux 模式和函数式编程有较深的理解。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;一句话点评&lt;/strong&gt;：内力最深厚，戒律最森严的「武林盟主」，最适合构建需要长期执政、规模宏大的「软件王朝」。&lt;/p&gt;&#xA;&lt;h2 id=&#34;简洁灵动武当akita&#34;&gt;简洁灵动「武当」：Akita&lt;a class=&#34;anchor&#34; href=&#34;#%e7%ae%80%e6%b4%81%e7%81%b5%e5%8a%a8%e6%ad%a6%e5%bd%93akita&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;武功心法&lt;/strong&gt;：不走纯函数路线，更偏向开发者熟悉的「面向对象」（OOP）之道。它认为状态管理不应那么复杂，讲究的是「大道至简」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;独门绝技&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Store &amp;amp; Query 分离&lt;/strong&gt;：&lt;code&gt;Store&lt;/code&gt; 只管存放和更新数据，&lt;code&gt;Query&lt;/code&gt; 只管读取和订阅数据。权责分明，心智模型简单。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;实体管理大师&lt;/strong&gt;：内置对实体集合（如用户列表）的强大支持，增删改查、管理「当前选中项」（active state）等操作，手到擒来，极其便利。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;修行门槛&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;样板代码极少&lt;/strong&gt;：对比 NgRx，Akita 的代码量可以说是「清风拂面」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;更「魔法」一点&lt;/strong&gt;：允许直接在 &lt;code&gt;Store&lt;/code&gt; 上调用 &lt;code&gt;update&lt;/code&gt; 方法来修改状态，这让函数式纯粹主义者感到「不够纯粹」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;&lt;strong&gt;一句话点评&lt;/strong&gt;：招式简明，直观易懂的「武当派」，特别适合那些需要大量处理范式化数据，又不想被 NgRx 繁琐仪式束缚的团队。&lt;/p&gt;&#xA;&lt;h2 id=&#34;新锐刺客elf&#34;&gt;新锐「刺客」：Elf&lt;a class=&#34;anchor&#34; href=&#34;#%e6%96%b0%e9%94%90%e5%88%ba%e5%ae%a2elf&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;武功心法&lt;/strong&gt;：由 Akita 同一个师门（Netanel Basal）新创的武学，旨在成为「你梦寐以求的状态管理库」。它集简洁、高效、现代于一身，招式更加「锐利」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;独门绝技&lt;/strong&gt;：&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;Immer.js 加持&lt;/strong&gt;：允许你用「可变」（mutable）的方式去写更新逻辑，但底层会自动为你生成「不可变」（immutable）的新状态。两全其美！&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 看似在修改老状态，实则招式已化为无形&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;store&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;update&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;state&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;state&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;user&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;雪狼&amp;#39;&lt;/span&gt;; });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;极简 API&lt;/strong&gt;：API 设计极其考究，旨在用最少的代码做最多的事，开发者体验极佳。&lt;/p&gt;</description>
    </item>
    <item>
      <title>6.Angular状态管理进阶：当心流与数据同步不再是难题</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/060-angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E8%BF%9B%E9%98%B6%E5%BD%93%E5%BF%83%E6%B5%81%E4%B8%8E%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%E4%B8%8D%E5%86%8D%E6%98%AF%E9%9A%BE%E9%A2%98/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/060-angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E8%BF%9B%E9%98%B6%E5%BD%93%E5%BF%83%E6%B5%81%E4%B8%8E%E6%95%B0%E6%8D%AE%E5%90%8C%E6%AD%A5%E4%B8%8D%E5%86%8D%E6%98%AF%E9%9A%BE%E9%A2%98/</guid>
      <description>&lt;p&gt;你已经学会了用 &lt;code&gt;BehaviorSubject&lt;/code&gt; 或 &lt;code&gt;signal&lt;/code&gt; 来管理状态，你的组件已经能通过服务实现「心电感应」，这很棒。但很快，你遇到了一个新的、更棘手的难题：&lt;strong&gt;与服务器的异步数据同步&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;这个难题，不仅仅是「拿到数据」那么简单。它是一个完整的故事，包含了「开始寻找（Loading）」、「满载而归（Data）」和「中途遇险（Error）」这三个章节。很多开发者只关心「满载而归」的主线剧情，却忽略了前奏和意外，导致用户体验支离破碎：没有加载提示，没有错误反馈，只有突兀的白屏和无尽的等待。&lt;/p&gt;&#xA;&lt;p&gt;今天，我们就来修炼一门进阶「心法」，让你能将这整个异步故事，优雅地、完整地讲述出来。&lt;/p&gt;&#xA;&lt;h2 id=&#34;问题的核心异步数据天生就有三种形态&#34;&gt;问题的核心：异步数据天生就有「三种形态」&lt;a class=&#34;anchor&#34; href=&#34;#%e9%97%ae%e9%a2%98%e7%9a%84%e6%a0%b8%e5%bf%83%e5%bc%82%e6%ad%a5%e6%95%b0%e6%8d%ae%e5%a4%a9%e7%94%9f%e5%b0%b1%e6%9c%89%e4%b8%89%e7%a7%8d%e5%bd%a2%e6%80%81&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;任何一个从远方（服务器）取来的数据，在它抵达你手中之前，都必然经历三种或三种之一的状态：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;加载中 (Loading)&lt;/strong&gt;：信使已经派出，正在路上。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;已获取 (Data)&lt;/strong&gt;：信使成功带回了情报。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;出错了 (Error)&lt;/strong&gt;：信使在路上被劫或迷路了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;一个成熟的状态管理方案，必须能清晰地追踪并向视图反映这三种形态。如果你还在组件里用 &lt;code&gt;isLoading = true&lt;/code&gt;、&lt;code&gt;isError = false&lt;/code&gt; 这样的布尔值「膏药」来手动管理，那么你的「心流」很快就会被这些琐碎的状态搅乱。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;angular_state_images/async_state_flow.jpg&#34; alt=&#34;文生图：一个流程图，清晰地展示了异步数据的三种状态。一个请求发出后，流向一个loading状态的沙漏；然后分叉，一条成功路径指向一个装着数据的宝箱（data），另一条失败路径指向一个破碎的图标（error）。风格：简洁、清晰的信息图表。&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;进阶心法状态化数据流模式&#34;&gt;进阶心法：「状态化数据流」模式&lt;a class=&#34;anchor&#34; href=&#34;#%e8%bf%9b%e9%98%b6%e5%bf%83%e6%b3%95%e7%8a%b6%e6%80%81%e5%8c%96%e6%95%b0%e6%8d%ae%e6%b5%81%e6%a8%a1%e5%bc%8f&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;我们的目标是，只用&lt;strong&gt;一个数据流&lt;/strong&gt;，就能完整地描述这整个异步故事。如何做到？答案是：&lt;strong&gt;不要让你的流只承载「数据」本身，而是让它承载一个包含了所有状态的「状态对象」&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;首先，定义这个「状态对象」的契约：&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;AsyncState&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;T&lt;/span&gt;&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;loading&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;boolean&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;T&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;any&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;|&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;现在，让我们以 RxJS 为例，来构建一个会讲故事的数据流。&lt;/p&gt;&#xA;&lt;h3 id=&#34;绝美姿势用-pipe-编排整个故事&#34;&gt;绝美「姿势」：用 &lt;code&gt;pipe&lt;/code&gt; 编排整个故事&lt;a class=&#34;anchor&#34; href=&#34;#%e7%bb%9d%e7%be%8e%e5%a7%bf%e5%8a%bf%e7%94%a8-pipe-%e7%bc%96%e6%8e%92%e6%95%b4%e4%b8%aa%e6%95%85%e4%ba%8b&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;p&gt;让我们用一系列 RxJS 操作符，来声明式地编排这个故事。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// products.service.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;startWith&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;switchMap&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;map&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;catchError&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;shareReplay&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rxjs/operators&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Subject&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;Observable&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rxjs&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;HttpClient&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@angular/common/http&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Injectable&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;inject&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@angular/core&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Product&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;number&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@Injectable&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;providedIn&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt; })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;ProductService&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;httpClient&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;inject&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;HttpClient&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 一个「扳机」，用来命令「重新加载」&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reloadSource&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Subject&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;void&lt;/span&gt;&amp;gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 这就是那条会讲故事的、优雅的数据流&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;state$&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Observable&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;AsyncState&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;Product&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;[]&lt;/span&gt;&amp;gt;&amp;gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;reloadSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;pipe&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 让流在第一时间（或每次被命令时）启动&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;startWith&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 核心：每当启动时，切换到一个新的「取货任务」流&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;switchMap&lt;/span&gt;(() &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 这就是「取货任务」流&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;httpClient&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;Product&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;[]&lt;/span&gt;&amp;gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/api/products&amp;#39;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;pipe&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 4. 如果成功，把「货物」包装成「成功」状态&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;map&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; ({ &lt;span style=&#34;color:#a6e22e&#34;&gt;loading&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; })),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;// 5. 如果失败，把「事故」包装成「失败」状态&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;catchError&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;loading&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt; }))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      )&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 6. 神来之笔：在每次「取货任务」开始前，先插播一个「加载中」的状态&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;startWith&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;loading&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;data&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;error&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt; }),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// 7. 让这条流变成「直播」，共享给所有订阅者&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;shareReplay&lt;/span&gt;(&lt;span style=&#34;color:#ae81ff&#34;&gt;1&lt;/span&gt;)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 公开的「扳机」方法&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;reload&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;reloadSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;next&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这段代码的美，在于它将一个复杂的异步工作流（开始 -&amp;gt; 请求 -&amp;gt; 成功/失败）完全用一条声明式的管道来定义。我们没有「做」任何事，我们只是「描述」了状态应该如何根据事件流转。&lt;/p&gt;</description>
    </item>
    <item>
      <title>7.打造你的专属Angular状态管理：从设计到实现</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/070-%E6%89%93%E9%80%A0%E4%BD%A0%E7%9A%84%E4%B8%93%E5%B1%9Eangular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%BB%8E%E8%AE%BE%E8%AE%A1%E5%88%B0%E5%AE%9E%E7%8E%B0/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/070-%E6%89%93%E9%80%A0%E4%BD%A0%E7%9A%84%E4%B8%93%E5%B1%9Eangular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%BB%8E%E8%AE%BE%E8%AE%A1%E5%88%B0%E5%AE%9E%E7%8E%B0/</guid>
      <description>&lt;p&gt;在深入了解了各种状态管理模式和现成的库（NgRx, Akita&amp;hellip;）之后，你是否会产生一种敬畏，觉得它们内部的实现高深莫测，是只有框架作者才能触及的「黑魔法」？&lt;/p&gt;&#xA;&lt;p&gt;今天，我们就来亲手打破这个迷思。雪狼将手把手带你，仅用几十行代码，打造一个我们专属的、可复用的、通用的状态管理基类 —— 一个迷你版的「NgRx」。&lt;/p&gt;&#xA;&lt;p&gt;这个过程，不仅会让你拥有一个属于自己的实用工具，更重要的是，它将让你彻底洞悉所有状态管理库背后的核心思想，完成从「知识消费者」到「模式创造者」的蜕变。&lt;/p&gt;&#xA;&lt;h2 id=&#34;我们的目标一个可复用的-store-基类&#34;&gt;我们的目标：一个可复用的 &lt;code&gt;Store&lt;/code&gt; 基类&lt;a class=&#34;anchor&#34; href=&#34;#%e6%88%91%e4%bb%ac%e7%9a%84%e7%9b%ae%e6%a0%87%e4%b8%80%e4%b8%aa%e5%8f%af%e5%a4%8d%e7%94%a8%e7%9a%84-store-%e5%9f%ba%e7%b1%bb&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;我们不希望每个需要管理状态的服务（&lt;code&gt;UsersStore&lt;/code&gt;, &lt;code&gt;ProductsStore&lt;/code&gt;&amp;hellip;）都重复去写状态管理的样板代码。我们想要一个 &lt;code&gt;Store&amp;lt;T&amp;gt;&lt;/code&gt; 基类，它能帮我们处理掉所有「脏活累活」。任何具体的业务 Store，只需继承它，然后专注于自己的业务逻辑即可。&lt;/p&gt;&#xA;&lt;p&gt;这个基类需要具备：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;一个封装好的、私有的状态容器。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;一个可供外部订阅的、公开的只读状态视图。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;一套安全、规范的内部状态更新机制。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;img src=&#34;angular_state_images/store_inheritance.jpg&#34; alt=&#34;文生图：一个清晰的类继承图。顶层是一个抽象的Store&amp;lt;T&amp;gt;基类，下面有几个具体的子类，如TodosStore, UsersStore，都通过箭头指向基类，展示了继承关系。风格：UML图、信息图表、简洁。&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;v1经典的-rxjs-版本&#34;&gt;V1：经典的 RxJS 版本&lt;a class=&#34;anchor&#34; href=&#34;#v1%e7%bb%8f%e5%85%b8%e7%9a%84-rxjs-%e7%89%88%e6%9c%ac&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;h3 id=&#34;第一步搭建骨架封装-behaviorsubject&#34;&gt;第一步：搭建骨架，封装 &lt;code&gt;BehaviorSubject&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#%e7%ac%ac%e4%b8%80%e6%ad%a5%e6%90%ad%e5%bb%ba%e9%aa%a8%e6%9e%b6%e5%b0%81%e8%a3%85-behaviorsubject&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// rxjs-store.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Observable&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;BehaviorSubject&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rxjs&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;abstract&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RxjsStore&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;T&lt;/span&gt;&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;BehaviorSubject&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;T&lt;/span&gt;&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;readonly&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;state$&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Observable&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;T&lt;/span&gt;&amp;gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;constructor&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;initialState&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;T&lt;/span&gt;) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;BehaviorSubject&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;T&lt;/span&gt;&amp;gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;initialState&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;state$&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;asObservable&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;getState&lt;/span&gt;()&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;T&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getValue&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;protected&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;setState&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;newState&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Partial&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;T&lt;/span&gt;&amp;gt;)&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;currentState&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getState&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;nextState&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; { ...&lt;span style=&#34;color:#a6e22e&#34;&gt;currentState&lt;/span&gt;, ...&lt;span style=&#34;color:#a6e22e&#34;&gt;newState&lt;/span&gt; };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;stateSource&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;next&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;nextState&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;通过 &lt;code&gt;private readonly&lt;/code&gt; 和 &lt;code&gt;asObservable()&lt;/code&gt;，我们建立了一道「防火墙」，确保了外界只能「看」（订阅），不能「摸」（直接调用 &lt;code&gt;.next()&lt;/code&gt;）。&lt;/p&gt;&#xA;&lt;h3 id=&#34;第二步学以致用创建-todosstore&#34;&gt;第二步：学以致用，创建 &lt;code&gt;TodosStore&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#%e7%ac%ac%e4%ba%8c%e6%ad%a5%e5%ad%a6%e4%bb%a5%e8%87%b4%e7%94%a8%e5%88%9b%e5%bb%ba-todosstore&#34;&gt;#&lt;/a&gt;&lt;/h3&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// todos.store.ts&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Injectable&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@angular/core&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;RxjsStore&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;./rxjs-store&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// ... 定义 TodosState, Todo 接口&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@Injectable&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;providedIn&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;root&amp;#39;&lt;/span&gt; })&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;TodosStore&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;extends&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;RxjsStore&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;TodosState&lt;/span&gt;&amp;gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;constructor&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;super&lt;/span&gt;({ &lt;span style=&#34;color:#a6e22e&#34;&gt;todos&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [], &lt;span style=&#34;color:#a6e22e&#34;&gt;filter&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;ALL&amp;#39;&lt;/span&gt; });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;addTodo&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;text&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;void&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;newTodo&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Todo&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;Date.now&lt;/span&gt;(), &lt;span style=&#34;color:#a6e22e&#34;&gt;text&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;completed&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt; };&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;setState&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#a6e22e&#34;&gt;todos&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [...&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;getState&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;todos&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;newTodo&lt;/span&gt;],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// ... 其他方法&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;TodosStore&lt;/code&gt; 只需专注于自己的业务逻辑，所有通用的状态管理机制，都已经被 &lt;code&gt;RxjsStore&lt;/code&gt; 基类完美封装了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>8.状态管理的“度”：Angular中如何避免“过度设计”</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/080-%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E7%9A%84%E5%BA%A6angular%E4%B8%AD%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E8%BF%87%E5%BA%A6%E8%AE%BE%E8%AE%A1/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/080-%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E7%9A%84%E5%BA%A6angular%E4%B8%AD%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D%E8%BF%87%E5%BA%A6%E8%AE%BE%E8%AE%A1/</guid>
      <description>&lt;p&gt;你的任务是：在墙上挂一幅画。&lt;/p&gt;&#xA;&lt;p&gt;方案 A：你用大拇指奋力把钉子往墙里按。指甲翻了，墙皮掉了，钉子弯了，画没挂上。&lt;/p&gt;&#xA;&lt;p&gt;方案 B：你从仓库里请出了一把80磅重的攻城锤。一锤下去，墙塌了。&lt;/p&gt;&#xA;&lt;p&gt;听起来很荒谬，对吗？但在我们的代码世界里，这种事每天都在发生。前者，是拒绝任何状态管理，试图用 &lt;code&gt;input()&lt;/code&gt; 和 &lt;code&gt;@Output&lt;/code&gt; 摆平一切的「原始人」；后者，是为了一个简单的表单就 &lt;code&gt;ng add @ngrx/store&lt;/code&gt; 的「军备竞赛」爱好者。&lt;/p&gt;&#xA;&lt;p&gt;这两种极端，都源于对状态管理之「度」的失察。好的架构，不在于武力的强大，而在于分寸的得当。&lt;/p&gt;&#xA;&lt;h2 id=&#34;不作为之罪当简单变成混乱&#34;&gt;不作为之罪：当「简单」变成「混乱」&lt;a class=&#34;anchor&#34; href=&#34;#%e4%b8%8d%e4%bd%9c%e4%b8%ba%e4%b9%8b%e7%bd%aa%e5%bd%93%e7%ae%80%e5%8d%95%e5%8f%98%e6%88%90%e6%b7%b7%e4%b9%b1&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;症状&lt;/strong&gt;：你的应用里，一个数据需要从顶层组件，一路通过 &lt;code&gt;input()&lt;/code&gt; 属性传递五层，才能到达最终需要它的那个孙子组件。而这个孙子组件的一个点击，又需要通过五层 &lt;code&gt;@Output&lt;/code&gt; 事件冒泡，才能通知到顶层组件去更新数据。中间那四个「中转」组件，它们本身根本不关心这个数据，却被迫当起了「传话筒」。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;病因&lt;/strong&gt;：这是一种「鸵鸟心态」 —— 「我的应用很简单，不需要什么状态管理」。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;恶果&lt;/strong&gt;：这种心态，恰恰是制造复杂的根源。当应用稍微生长，这种「人肉传递」模式就会让组件之间形成错综复杂的强耦合。修改一个数据，你需要在一长串组件链上进行修改，维护成本呈指数级增长。你所谓的「简单」，最终变成了最令人头疼的「混乱」。&lt;/p&gt;&#xA;&lt;h2 id=&#34;乱作为之罪当最佳实践变成过度设计&#34;&gt;乱作为之罪：当「最佳实践」变成「过度设计」&lt;a class=&#34;anchor&#34; href=&#34;#%e4%b9%b1%e4%bd%9c%e4%b8%ba%e4%b9%8b%e7%bd%aa%e5%bd%93%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5%e5%8f%98%e6%88%90%e8%bf%87%e5%ba%a6%e8%ae%be%e8%ae%a1&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;&lt;strong&gt;症状&lt;/strong&gt;：你接手一个需求，做一个简单的「公司简介」页面，上面有个联系我们的小表单。你立刻打开终端，熟练地敲下 &lt;code&gt;ng add @ngrx/store&lt;/code&gt;，然后花半天时间，一丝不苟地定义 &lt;code&gt;Actions&lt;/code&gt;, &lt;code&gt;Reducers&lt;/code&gt;, &lt;code&gt;Effects&lt;/code&gt;，只为了管理那个表单的提交状态。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;病因&lt;/strong&gt;：这是「简历驱动开发」或「权威崇拜」的典型表现 —— 「NgRx 是 Angular 的最佳实践，我得用上」，「谷歌也在用，那肯定就是对的」。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;恶果&lt;/strong&gt;：你用「攻城锤」去砸钉子。为了一个本地化的、生命周期短暂的状态，你引入了全局的、复杂的、需要大量样板代码的「国家机器」。代码变得更难阅读，新同事需要花更多时间来理解你那「杀鸡用牛刀」的宏伟设计。这，就是典型的&lt;strong&gt;过度设计（Over-engineering）&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;angular_degree_images/overengineering.jpg&#34; alt=&#34;文生图：一个天平，左边的托盘上放着一把小小的锤子，下面写着“问题复杂度”；右边的托盘上放着一把巨大的、火箭助推的“雷神之锤”，下面写着“解决方案复杂度”。天平严重向右倾斜，失去平衡。风格：讽刺漫画。&#34; /&gt;&lt;/p&gt;&#xA;&lt;h2 id=&#34;中庸之道如何找到恰如其分的度&#34;&gt;中庸之道：如何找到恰如其分的「度」？&lt;a class=&#34;anchor&#34; href=&#34;#%e4%b8%ad%e5%ba%b8%e4%b9%8b%e9%81%93%e5%a6%82%e4%bd%95%e6%89%be%e5%88%b0%e6%81%b0%e5%a6%82%e5%85%b6%e5%88%86%e7%9a%84%e5%ba%a6&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;真正的智慧，在于「权衡」，在于为不同规模的问题，匹配不同量级的解决方案。让我们再次审视状态管理的「光谱」，并学会如何诊断问题。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;诊断清单：&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;这个状态是「谁」的？&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;只跟某个组件自己的外观和行为有关？（如一个下拉菜单是否展开）。这是&lt;strong&gt;组件本地状态&lt;/strong&gt;，用一个简单的 &lt;code&gt;signal&lt;/code&gt; 就够了。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;只跟一个父组件和它的几个孩子有关？这是&lt;strong&gt;父子状态&lt;/strong&gt;，用 &lt;code&gt;input()&lt;/code&gt; 和 &lt;code&gt;@Output&lt;/code&gt; 解决。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;只跟某个功能模块内（如「用户中心」）的几个页面有关？这是&lt;strong&gt;功能模块状态&lt;/strong&gt;，一个简单的 &lt;code&gt;BehaviorSubject&lt;/code&gt; 或 &lt;code&gt;signal&lt;/code&gt; 服务是你的最佳选择。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;整个应用的不同模块（如「头部」、「购物车」、「个人主页」）都需要共享和修改？这才是&lt;strong&gt;真正的全局状态&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;这个状态要「活」多久？&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;组件销毁，它就该死？那么它就不应该被放到全局服务里。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;离开这个功能模块，它就没用了？那它就不应该是全局的。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;p&gt;&lt;strong&gt;黄金法则：永远从最简单的方案开始。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;先用组件本地状态 (&lt;code&gt;signal&lt;/code&gt;) -&amp;gt; 如果不行 -&amp;gt; 升级到共享服务 -&amp;gt; 如果还不行（比如多个服务间的状态依赖变得复杂） -&amp;gt; &lt;strong&gt;再考虑&lt;/strong&gt;引入专业的全局状态管理库。&lt;/p&gt;</description>
    </item>
    <item>
      <title>9.Angular数据流的“禅意”：RxJS与Signals在状态管理中的深度应用</title>
      <link>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/090-angular%E6%95%B0%E6%8D%AE%E6%B5%81%E7%9A%84%E7%A6%85%E6%84%8Frxjs%E4%B8%8Esignals%E5%9C%A8%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%B8%AD%E7%9A%84%E6%B7%B1%E5%BA%A6%E5%BA%94%E7%94%A8/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>/angular/angular%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%B7%B1%E5%BA%A6%E6%8E%A2%E7%B4%A2/090-angular%E6%95%B0%E6%8D%AE%E6%B5%81%E7%9A%84%E7%A6%85%E6%84%8Frxjs%E4%B8%8Esignals%E5%9C%A8%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E4%B8%AD%E7%9A%84%E6%B7%B1%E5%BA%A6%E5%BA%94%E7%94%A8/</guid>
      <description>&lt;p&gt;在武学修炼中，上乘境界讲究「心流合一」，意动而力至，无思而有为。在 Angular 的世界里，要达到这种编程的「禅定」之境，关键在于掌握「数据流」的奥秘。&lt;/p&gt;&#xA;&lt;p&gt;多年以来，我们修行的是 &lt;strong&gt;RxJS 的「水之道」&lt;/strong&gt;。它视万物为&lt;strong&gt;时间长河中的事件流&lt;/strong&gt;，讲究顺势而为，以柔克刚。而今，Angular 引入了 &lt;strong&gt;Signals 的「光之道」&lt;/strong&gt;。它视万物为&lt;strong&gt;瞬时触发的依赖网&lt;/strong&gt;，讲究精准打击，直达病灶。&lt;/p&gt;&#xA;&lt;p&gt;这两种「道」，是相互排斥的「生死之敌」，还是可以互补的「阴阳太极」？这便是我们今天要探讨的，数据流的终极「禅意」。&lt;/p&gt;&#xA;&lt;h2 id=&#34;水之道rxjs事件长河的编舞者&#34;&gt;水之道：RxJS，事件长河的编舞者&lt;a class=&#34;anchor&#34; href=&#34;#%e6%b0%b4%e4%b9%8b%e9%81%93rxjs%e4%ba%8b%e4%bb%b6%e9%95%bf%e6%b2%b3%e7%9a%84%e7%bc%96%e8%88%9e%e8%80%85&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;禅意&lt;/strong&gt;：RxJS 的世界观是动态的、连续的。它不关心某个「状态」本身，它关心的是「状态的变化过程」。一次点击、一次网络请求、一次用户输入，在它眼中，都是一条流淌的、包含无限可能的「事件之河」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;所长&lt;/strong&gt;：&lt;strong&gt;异步流程的编排&lt;/strong&gt;。这是 RxJS 无可替代的「神之领域」。当你的逻辑是「监听用户输入，等待300毫秒，如果值有变化，就发起 API 请求，并取消上一次未完成的请求」，这种涉及到「时间」和「事件」的复杂异步舞蹈，正是 &lt;code&gt;debounceTime&lt;/code&gt; 和 &lt;code&gt;switchMap&lt;/code&gt; 大展拳脚的舞台。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;公案&lt;/strong&gt;：「水」本身是无形的、流动的，但我们却常常用它来承载有形的「状态」（&lt;code&gt;BehaviorSubject&lt;/code&gt;）。这就像试图用一条河去描述一个湖的状态。我们做得到，但这其中蕴含着一种哲学上的「不自然」，也是其复杂性的来源之一。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;光之道signals依赖图谱的构建者&#34;&gt;光之道：Signals，依赖图谱的构建者&lt;a class=&#34;anchor&#34; href=&#34;#%e5%85%89%e4%b9%8b%e9%81%93signals%e4%be%9d%e8%b5%96%e5%9b%be%e8%b0%b1%e7%9a%84%e6%9e%84%e5%bb%ba%e8%80%85&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;禅意&lt;/strong&gt;：Signals 的世界观是静态的、依赖性的。它不关心「时间」，它只关心「谁依赖于谁」。当一个值变化时，它像一道光，瞬间就能沿着预先构建好的「依赖图谱」，精准地通知到所有相关的「节点」。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;所长&lt;/strong&gt;：&lt;strong&gt;同步状态的管理&lt;/strong&gt;。这是 Signals 的「绝对主场」。当你有一系列互相关联的、在内存中同步存在的状态时（比如 &lt;code&gt;firstName&lt;/code&gt; 和 &lt;code&gt;lastName&lt;/code&gt;），用 &lt;code&gt;computed&lt;/code&gt; 去派生出 &lt;code&gt;fullName&lt;/code&gt;，其心智模型之简单、性能之高效，是 RxJS 难以比拟的。它剔除了所有与「时间」相关的复杂性。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;公案&lt;/strong&gt;：「光」的传播是瞬时的、同步的，但它所承载的「信息」（状态）却往往来自于异步的「远方」。&lt;code&gt;mySignal.set(value)&lt;/code&gt; 这个动作本身是同步的，但 &lt;code&gt;value&lt;/code&gt; 从何而来？通常是在一个 &lt;code&gt;Promise.then()&lt;/code&gt; 或 &lt;code&gt;Observable.subscribe()&lt;/code&gt; 的异步回调中。&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;禅境水光交融阴阳合一&#34;&gt;禅境：水光交融，阴阳合一&lt;a class=&#34;anchor&#34; href=&#34;#%e7%a6%85%e5%a2%83%e6%b0%b4%e5%85%89%e4%ba%a4%e8%9e%8d%e9%98%b4%e9%98%b3%e5%90%88%e4%b8%80&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;「水之道」与「光之道」并非对立，而是互补。真正的禅意，在于「物尽其用，道法自然」。&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;终极模式：用 RxJS 处理「过程」，用 Signals 承载「结果」。&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;p&gt;用「水」（RxJS）去驯服那条狂野、不可预测的「异步事件之河」。当河水历经九曲十八弯，最终变得清澈、稳定，汇入「湖泊」（组件）的那一刻，我们施展「点石成金」之术，将「水」化为「光」（Signal），用它来照亮我们的庙堂（视图）。&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;angular_state_images/rxjs_to_signal_bridge.jpg&#34; alt=&#34;文生图：一座科技感十足的“桥梁”，桥的一端是流淌的蓝色“数据之河”（RxJS），另一端是发出金色光芒的“信号塔”（Signals）。桥的中央有一个toSignal的标志，河水流经桥梁时被转化为光能，传输到信号塔。风格：概念插画、科技感。&#34; /&gt;&lt;/p&gt;&#xA;&lt;p&gt;Angular 团队为我们提供了连接这两个世界的「桥梁」 —— &lt;code&gt;@angular/core/rxjs-interop&lt;/code&gt; 中的 &lt;code&gt;toSignal&lt;/code&gt;。&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-typescript&#34; data-lang=&#34;typescript&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;toSignal&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@angular/core/rxjs-interop&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;Component&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;inject&lt;/span&gt;, &lt;span style=&#34;color:#a6e22e&#34;&gt;computed&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@angular/core&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;HttpClient&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@angular/common/http&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;catchError&lt;/span&gt;, &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;rxjs&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;interface&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;Product&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;id&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;number&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;name&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;string&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;@Component&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;standalone&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;true&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;selector&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;app-product-list&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;template&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;`&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    @if (products(); as prods) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;lt;ul&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        @for (p of prods; track p.id) {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;          &amp;lt;li&amp;gt;{{ p.name }}&amp;lt;/li&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;        }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;lt;/ul&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    } @else {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;      &amp;lt;p&amp;gt;加载中或无产品&amp;lt;/p&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    &amp;lt;p&amp;gt;产品数量: {{ productsCount() }}&amp;lt;/p&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;    &amp;lt;p&amp;gt;是否有产品: {{ hasProducts() }}&amp;lt;/p&amp;gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#e6db74&#34;&gt;  `&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;MyComponent&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;httpClient&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;inject&lt;/span&gt;(&lt;span style=&#34;color:#a6e22e&#34;&gt;HttpClient&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 1. 「水之道」：用 RxJS 优雅地处理复杂的异步获取逻辑&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;productsHttp$&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;httpClient&lt;/span&gt;.&lt;span style=&#34;color:#66d9ef&#34;&gt;get&lt;/span&gt;&amp;lt;&lt;span style=&#34;color:#f92672&#34;&gt;Product&lt;/span&gt;&lt;span style=&#34;color:#960050;background-color:#1e0010&#34;&gt;[]&lt;/span&gt;&amp;gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/api/products&amp;#39;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;pipe&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;catchError&lt;/span&gt;(() &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;of&lt;/span&gt;([])) &lt;span style=&#34;color:#75715e&#34;&gt;// 容错处理&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#75715e&#34;&gt;// ... 其他复杂的 RxJS 操作&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  );&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 2. 「桥梁」：toSignal 将「水」化为「光」&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 它会自动订阅 Observable，并将流出的最新值，存入一个 Signal 中。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 它还会负责在组件销毁时自动退订。&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;products&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;toSignal&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;productsHttp$&lt;/span&gt;, { &lt;span style=&#34;color:#a6e22e&#34;&gt;initialValue&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [] });&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#75715e&#34;&gt;// 3. 「光之道」：现在，你可以尽情享受 Signals 带来的简单与高效&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;productsCount&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;computed&lt;/span&gt;(() &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;products&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;length&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;hasProducts&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;computed&lt;/span&gt;(() &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;this&lt;/span&gt;.&lt;span style=&#34;color:#a6e22e&#34;&gt;productsCount&lt;/span&gt;() &lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#ae81ff&#34;&gt;0&lt;/span&gt;);&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;toSignal&lt;/code&gt; 就像一个「水力发电机」，它利用 RxJS 水流的强大动能，将其转化为 Signals 干净、高效的「电能」，驱动你的组件。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
