[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"i-ri:search-line":3,"i-ri:moon-line":8,"i-ri:sun-line":10,"i-ri:menu-3-line":12,"i-ri:close-line":14,"notes-module-items-react":16,"notes-page-react-10-routing-and-navigation\u002F01-routing-and-url-state-mental-model":494,"i-ri:arrow-left-s-line":1325,"i-ri:menu-2-line":1327,"i-ri:arrow-right-s-line":1329},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":7},0,24,false,"\u003Cpath fill=\"currentColor\" d=\"m18.031 16.617l4.283 4.282l-1.415 1.415l-4.282-4.283A8.96 8.96 0 0 1 11 20c-4.968 0-9-4.032-9-9s4.032-9 9-9s9 4.032 9 9a8.96 8.96 0 0 1-1.969 5.617m-2.006-.742A6.98 6.98 0 0 0 18 11c0-3.867-3.133-7-7-7s-7 3.133-7 7s3.133 7 7 7a6.98 6.98 0 0 0 4.875-1.975z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":9},"\u003Cpath fill=\"currentColor\" d=\"M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2h.1A6.98 6.98 0 0 0 10 7m-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938A8 8 0 0 0 4 12\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":11},"\u003Cpath fill=\"currentColor\" d=\"M12 18a6 6 0 1 1 0-12a6 6 0 0 1 0 12m0-2a4 4 0 1 0 0-8a4 4 0 0 0 0 8M11 1h2v3h-2zm0 19h2v3h-2zM3.515 4.929l1.414-1.414L7.05 5.636L5.636 7.05zM16.95 18.364l1.414-1.414l2.121 2.121l-1.414 1.414zm2.121-14.85l1.414 1.415l-2.121 2.121l-1.414-1.414zM5.636 16.95l1.414 1.414l-2.121 2.121l-1.414-1.414zM23 11v2h-3v-2zM4 11v2H1v-2z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":13},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm6 7h12v2H9zm-6 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":15},"\u003Cpath fill=\"currentColor\" d=\"m12 10.587l4.95-4.95l1.414 1.414l-4.95 4.95l4.95 4.95l-1.415 1.414l-4.95-4.95l-4.949 4.95l-1.414-1.415l4.95-4.95l-4.95-4.95L7.05 5.638z\"\u002F>",[17,22,26,30,34,38,42,46,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,254,258,262,266,270,274,278,282,286,290,294,298,302,306,310,314,318,322,326,330,334,338,342,346,350,354,358,362,366,370,374,378,382,386,390,394,398,402,406,410,414,418,422,426,430,434,438,442,446,450,454,458,462,466,470,474,478,482,486,490],{"path":18,"title":19,"meta":20},"\u002Fnotes\u002Freact\u002F01-basics\u002F01-how-to-read-this-repo","如何阅读本仓库（学习路径与章节依赖）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},"2026-11-05T09:47:15.000Z",{"path":23,"title":24,"meta":25},"\u002Fnotes\u002Freact\u002F01-basics\u002F02-render-vs-commit","React 渲染两阶段：Render vs Commit（总览）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":27,"title":28,"meta":29},"\u002Fnotes\u002Freact\u002F01-basics\u002F03-update-pipeline-birdview","从“更新”到“页面变更”：一次 setState 的全链路鸟瞰",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":31,"title":32,"meta":33},"\u002Fnotes\u002Freact\u002F01-basics","基础入门（建议先读）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":35,"title":36,"meta":37},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F01-browser-multi-process","浏览器多进程架构",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":39,"title":40,"meta":41},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F02-event-loop-overview","事件循环概述",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":43,"title":44,"meta":45},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F03-call-stack","函数调用栈",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":47,"title":48,"meta":49},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F04-threads","线程介绍",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":51,"title":52,"meta":53},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F05-refresh-rate-and-queues","刷新率与执行队列",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":55,"title":56,"meta":57},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F06-settimeout","setTimeout 原理详解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":59,"title":60,"meta":61},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F07-promise","Promise 原理详解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":63,"title":64,"meta":65},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F08-event-loop-in-practice","事件循环机制（综合）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":67,"title":68,"meta":69},"\u002Fnotes\u002Freact\u002F02-event-loop\u002F09-priority-queues","优先级队列",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":71,"title":72,"meta":73},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F01-concept","并发模式：概念",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":75,"title":76,"meta":77},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F02-demo","案例演示并发模式",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":79,"title":80,"meta":81},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F03-high-priority-preemption","高优先级插队",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":83,"title":84,"meta":85},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F04-preemption-vs-interruption","插队的影响、与中断的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":87,"title":88,"meta":89},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F05-shouldYield","中断条件：shouldYield",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":91,"title":92,"meta":93},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F06-react-tasks-and-queues","React 中的任务与队列",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":95,"title":96,"meta":97},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F07-ensureRootIsScheduled","ensureRootIsScheduled",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":99,"title":100,"meta":101},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F08-batch-updates-merge","合并多个更新触发",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":103,"title":104,"meta":105},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F09-taskQueue-lifecycle","taskQueue 队列循环的启动与结束",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":107,"title":108,"meta":109},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F10-time-slicing","时间切片是如何实现的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":111,"title":112,"meta":113},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F11-workLoop-full","workLoop 循环完整逻辑",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":115,"title":116,"meta":117},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F12-priority-design","React 中的优先级设计",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":119,"title":120,"meta":121},"\u002Fnotes\u002Freact\u002F03-concurrent-mode\u002F13-lane-model","lane 模型",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":123,"title":124,"meta":125},"\u002Fnotes\u002Freact\u002F04-fiber\u002F01-three-node-types","三种节点对象",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":127,"title":128,"meta":129},"\u002Fnotes\u002Freact\u002F04-fiber\u002F02-fiberRootNode","FiberRootNode",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":131,"title":132,"meta":133},"\u002Fnotes\u002Freact\u002F04-fiber\u002F03-fiber-tree","Fiber 树",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":135,"title":136,"meta":137},"\u002Fnotes\u002Freact\u002F04-fiber\u002F04-initial-mount-build","Fiber 树初始构建过程",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":139,"title":140,"meta":141},"\u002Fnotes\u002Freact\u002F04-fiber\u002F05-workLoopConcurrent","workLoopConcurrent",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":143,"title":144,"meta":145},"\u002Fnotes\u002Freact\u002F04-fiber\u002F06-stack-and-workInProgress","栈结构 与 workInProgress",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":147,"title":148,"meta":149},"\u002Fnotes\u002Freact\u002F04-fiber\u002F07-executionContext","执行上下文 executionContext",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":151,"title":152,"meta":153},"\u002Fnotes\u002Freact\u002F04-fiber\u002F08-update-lanes","update lanes",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":155,"title":156,"meta":157},"\u002Fnotes\u002Freact\u002F04-fiber\u002F09-render-lanes","render lanes",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":159,"title":160,"meta":161},"\u002Fnotes\u002Freact\u002F04-fiber\u002F10-fiber-lanes","fiber lanes",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":163,"title":164,"meta":165},"\u002Fnotes\u002Freact\u002F04-fiber\u002F11-flags-appendix","附录：flags",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":167,"title":168,"meta":169},"\u002Fnotes\u002Freact\u002F05-hooks\u002F01-background","hook 背景",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":171,"title":172,"meta":173},"\u002Fnotes\u002Freact\u002F05-hooks\u002F02-categories","hook 分类",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":175,"title":176,"meta":177},"\u002Fnotes\u002Freact\u002F05-hooks\u002F03-closures","hook 与闭包",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":179,"title":180,"meta":181},"\u002Fnotes\u002Freact\u002F05-hooks\u002F04-hooks-and-fiber","hook 与 fiber",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":183,"title":184,"meta":185},"\u002Fnotes\u002Freact\u002F05-hooks\u002F05-renderWithHooks","renderWithHooks",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":187,"title":188,"meta":189},"\u002Fnotes\u002Freact\u002F05-hooks\u002F06-init-state-hook","初始化 State Hook",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":191,"title":192,"meta":193},"\u002Fnotes\u002Freact\u002F05-hooks\u002F07-init-effect-hook","初始化 effect Hook",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":195,"title":196,"meta":197},"\u002Fnotes\u002Freact\u002F05-hooks\u002F08-circular-linked-list","环形链表详解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":199,"title":200,"meta":201},"\u002Fnotes\u002Freact\u002F05-hooks\u002F09-useReducer-vs-useState","useReducer 与 useState 的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":203,"title":204,"meta":205},"\u002Fnotes\u002Freact\u002F05-hooks\u002F10-update-linked-list","update 链表",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":207,"title":208,"meta":209},"\u002Fnotes\u002Freact\u002F05-hooks\u002F11-mount-state-updates","初始阶段的状态更新",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":211,"title":212,"meta":213},"\u002Fnotes\u002Freact\u002F05-hooks\u002F12-baseQueue-vs-pending","baseQueue 与 queue.pending",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":215,"title":216,"meta":217},"\u002Fnotes\u002Freact\u002F05-hooks\u002F13-dispatch-in-update","更新阶段的 dispatch",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":219,"title":220,"meta":221},"\u002Fnotes\u002Freact\u002F05-hooks\u002F14-commitRoot","commitRoot",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":223,"title":224,"meta":225},"\u002Fnotes\u002Freact\u002F06-diff\u002F01-update-overview","React 更新机制概述",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":227,"title":228,"meta":229},"\u002Fnotes\u002Freact\u002F06-diff\u002F02-diff-strategy","diff 策略",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":231,"title":232,"meta":233},"\u002Fnotes\u002Freact\u002F06-diff\u002F03-node-compare","节点比较方式",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":235,"title":236,"meta":237},"\u002Fnotes\u002Freact\u002F06-diff\u002F04-reconcileChildFibers","reconcileChildFibers",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":239,"title":240,"meta":241},"\u002Fnotes\u002Freact\u002F06-diff\u002F05-reconcileSingleElement","reconcileSingleElement",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":243,"title":244,"meta":245},"\u002Fnotes\u002Freact\u002F06-diff\u002F06-reconcileChildrenArray","reconcileChildrenArray",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":247,"title":248,"meta":249},"\u002Fnotes\u002Freact\u002F06-diff\u002F07-why-not-number-key","为什么不建议使用数字作为 key",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":251,"title":252,"meta":253},"\u002Fnotes\u002Freact\u002F07-event-system\u002F01-overview","事件系统概述",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":255,"title":256,"meta":257},"\u002Fnotes\u002Freact\u002F07-event-system\u002F02-event-plugin","事件插件",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":259,"title":260,"meta":261},"\u002Fnotes\u002Freact\u002F07-event-system\u002F03-event-pooling","事件池",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":263,"title":264,"meta":265},"\u002Fnotes\u002Freact\u002F07-event-system\u002F04-root-listeners","根节点事件绑定",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":267,"title":268,"meta":269},"\u002Fnotes\u002Freact\u002F07-event-system\u002F05-event-dispatch","事件触发",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":271,"title":272,"meta":273},"\u002Fnotes\u002Freact\u002F08-interview\u002F01-useEffect-vs-useLayoutEffect","useEffect 与 useLayoutEffect 的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":275,"title":276,"meta":277},"\u002Fnotes\u002Freact\u002F08-interview\u002F02-why-no-conditional-hooks","为什么 hook 不能写在条件判断里",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":279,"title":280,"meta":281},"\u002Fnotes\u002Freact\u002F08-interview\u002F03-understanding-concurrency","聊聊在 React 中，你对并发模式的理解",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":283,"title":284,"meta":285},"\u002Fnotes\u002Freact\u002F08-interview\u002F04-update-mechanism","聊聊 React 的更新机制原理",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":287,"title":288,"meta":289},"\u002Fnotes\u002Freact\u002F08-interview\u002F05-setState-sync-or-async","setState 是同步还是异步的？",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":291,"title":292,"meta":293},"\u002Fnotes\u002Freact\u002F08-interview\u002F06-useState-vs-useReducer","聊聊 useState 与 useReducer 的区别",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":295,"title":296,"meta":297},"\u002Fnotes\u002Freact\u002F08-interview\u002F07-closure-trap","聊聊闭包陷阱问题，以及如何解决",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":299,"title":300,"meta":301},"\u002Fnotes\u002Freact\u002F08-interview\u002F08-time-slicing-details","时间分片是如何实现的（任务拆分\u002F中断\u002F恢复）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":303,"title":304,"meta":305},"\u002Fnotes\u002Freact\u002F08-interview\u002F09-batched-updates-useState","聊聊 useState 的批处理更新机制",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":307,"title":308,"meta":309},"\u002Fnotes\u002Freact\u002F08-interview\u002F10-jsx-to-dom","JSX 是如何转变成为真实 DOM 的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":311,"title":312,"meta":313},"\u002Fnotes\u002Freact\u002F08-interview\u002F11-useCallback-impl","useCallback 的实现原理是什么",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":315,"title":316,"meta":317},"\u002Fnotes\u002Freact\u002F08-interview\u002F12-scheduling-mechanism","详细聊聊 React 的调度机制",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":319,"title":320,"meta":321},"\u002Fnotes\u002Freact\u002F08-interview\u002F13-priority-and-lanes","聊聊 React 的优先级机制（Lane 模型）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":323,"title":324,"meta":325},"\u002Fnotes\u002Freact\u002F08-interview\u002F14-diff-algorithm","React 的 Diff 算法是什么样的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":327,"title":328,"meta":329},"\u002Fnotes\u002Freact\u002F08-interview\u002F15-event-system","详细聊聊 React 的事件系统是如何实现的",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":331,"title":332,"meta":333},"\u002Fnotes\u002Freact\u002F08-interview\u002F16-portals-bubbling","React Portals 上的事件是否会冒泡到父组件，原理是什么",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":335,"title":336,"meta":337},"\u002Fnotes\u002Freact\u002F08-interview\u002F17-useEffect-impl","useEffect 的实现原理是什么",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":339,"title":340,"meta":341},"\u002Fnotes\u002Freact\u002F08-interview\u002F18-useContext-impl","请聊聊 useContext 的实现原理",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":343,"title":344,"meta":345},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F01-automatic-batching-and-flushsync","React 18 自动批处理（Automatic Batching）与 flushSync",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":347,"title":348,"meta":349},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F02-strictmode-and-idempotent-effects","React StrictMode：为什么会“双调用”？（源码\u002F机制视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":351,"title":352,"meta":353},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F03-transition-useTransition-useDeferredValue","Transition：startTransition \u002F useTransition \u002F useDeferredValue（机制视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":355,"title":356,"meta":357},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F04-suspense-loading-boundary-design","Suspense：加载态边界如何设计（机制\u002F架构视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":359,"title":360,"meta":361},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice\u002F05-error-boundary-reporting-and-recovery","Error Boundary：兜底、重试与上报（自研 vs Sentry）（机制\u002F架构视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":363,"title":364,"meta":365},"\u002Fnotes\u002Freact\u002F09-react-18-in-practice","React 18 实战（并发特性与默认行为）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":367,"title":368,"meta":369},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation\u002F01-routing-and-url-state-mental-model","路由与 URL State：统一心智模型（架构师视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":371,"title":372,"meta":373},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation\u002F02-tanstack-router-route-tree-search-loader-prefetch","TanStack Router（Vite \u002F SPA）：Route Tree \u002F Search \u002F Loader \u002F Prefetch（落地篇）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":375,"title":376,"meta":377},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation\u002F03-next-app-router-segments-layout-loading-error-not-found-prefetch","Next.js App Router：Segments \u002F Layouts \u002F Loading-Error-NotFound \u002F Prefetch（落地篇）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":379,"title":380,"meta":381},"\u002Fnotes\u002Freact\u002F10-routing-and-navigation","路由与导航（TanStack Router \u002F Next App Router）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":383,"title":384,"meta":385},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F01-state-layering-ui-server-url-global","状态分层：UI \u002F Server \u002F URL \u002F Global（架构师视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":387,"title":388,"meta":389},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F02-tanstack-query-caching-and-invalidation","TanStack Query：缓存模型与失效策略（Caching & Invalidation）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":391,"title":392,"meta":393},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F03-optimistic-updates-and-consistency","TanStack Query：乐观更新与一致性（Optimistic Updates & Consistency）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":395,"title":396,"meta":397},"\u002Fnotes\u002Freact\u002F11-data-layer\u002F04-form-architecture-react-hook-form-validation-performance-testability","表单架构：React Hook Form 的受控\u002F非受控、校验、性能与可测试性（架构师视角）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":399,"title":400,"meta":401},"\u002Fnotes\u002Freact\u002F11-data-layer","数据层（Server State \u002F 表单 \u002F 状态分层）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":403,"title":404,"meta":405},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F01-hydration-mismatch","Hydration mismatch（React \u002F Next.js）：成因、检测、排查清单与工程化规避",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":407,"title":408,"meta":409},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F01-nextjs-cache-revalidate-consistency-online-not-updating","Next.js 缓存\u002F重验证与一致性：避免「线上怎么不更新」事故（App Router）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":411,"title":412,"meta":413},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F02-csr-ssr-ssg-isr-how-to-choose","CSR vs SSR vs SSG vs ISR：怎么选？边界是什么？（体验 + 成本 + 一致性）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":415,"title":416,"meta":417},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery\u002F04-streaming-ssr-with-suspense","Streaming SSR + Suspense：提升前端感知性能的利器",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":419,"title":420,"meta":421},"\u002Fnotes\u002Freact\u002F12-rendering-and-delivery","渲染与交付（CSR\u002FSSR\u002FStreaming\u002FHydration\u002F缓存）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":423,"title":424,"meta":425},"\u002Fnotes\u002Freact\u002F13-production-readiness\u002F01-observability-logging-metrics-tracing","前端可观测性体系：日志、指标与链路追踪",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":427,"title":428,"meta":429},"\u002Fnotes\u002Freact\u002F13-production-readiness\u002F02-auth-and-web-security","鉴权与 Web 安全：OAuth, JWT, XSS, CSRF, CSP",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":431,"title":432,"meta":433},"\u002Fnotes\u002Freact\u002F13-production-readiness","生产可用性（错误\u002F可观测\u002F鉴权\u002F安全）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":435,"title":436,"meta":437},"\u002Fnotes\u002Freact\u002F14-performance\u002F01-performance-playbook-and-metrics","前端性能定位 Playbook：从指标到归因",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":439,"title":440,"meta":441},"\u002Fnotes\u002Freact\u002F14-performance\u002F02-rendering-optimization-memo-context-virtualization","React 渲染性能优化：Memo, Context, 与虚拟化",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":443,"title":444,"meta":445},"\u002Fnotes\u002Freact\u002F14-performance\u002F03-asset-and-bundle-optimization","资源与 Bundle 优化：代码分割、图片与 CDN",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":447,"title":448,"meta":449},"\u002Fnotes\u002Freact\u002F14-performance","性能体系（定位 → 优化 → 度量）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":451,"title":452,"meta":453},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F01-component-system-and-design-system","组件体系与设计系统：构建规模化前端的基石",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":455,"title":456,"meta":457},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F02-testing-strategy-rtl-e2e-testability","前端测试体系：RTL, E2E 与可测性设计",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":459,"title":460,"meta":461},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F03-monorepo-and-dependency-management","Monorepo 与依赖治理：pnpm 和 Turborepo",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":463,"title":464,"meta":465},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F04-cicd-and-quality-gates","CI\u002FCD 与质量门禁：构建可靠的自动化流程",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":467,"title":468,"meta":469},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture\u002F05-bff-and-api-design","BFF 与 API 设计：前端架构师的视角",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":471,"title":472,"meta":473},"\u002Fnotes\u002Freact\u002F15-engineering-and-architecture","工程与架构治理（规模化）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":475,"title":476,"meta":477},"\u002Fnotes\u002Freact\u002F16-advanced\u002F01-rsc-and-server-actions-deep-dive","RSC\u002FServer Actions 深水区：边界、约束与缓存一致性",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":479,"title":480,"meta":481},"\u002Fnotes\u002Freact\u002F16-advanced\u002F02-micro-frontend-governance","微前端治理：样式、路由与通信",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":483,"title":484,"meta":485},"\u002Fnotes\u002Freact\u002F16-advanced\u002F03-realtime-and-offline","实时与离线：WebSocket, PWA 与 Service Worker",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":487,"title":488,"meta":489},"\u002Fnotes\u002Freact\u002F16-advanced\u002F04-a11y-i18n-compliance","a11y, i18n 与合规：构建负责任的全球化应用",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"path":491,"title":492,"meta":493},"\u002Fnotes\u002Freact\u002F16-advanced","进阶专题（按业务需要选做）",{"date":-1,"tags":-1,"summary":-1,"lastUpdated":21},{"id":495,"type":496,"sourcePath":497,"routePath":367,"path":367,"title":368,"updatedAt":21,"meta":498,"body":500,"toc":1301},"bm90ZTpub3Rlcy9yZWFjdC8xMC1yb3V0aW5nLWFuZC1uYXZpZ2F0aW9uLzAxLXJvdXRpbmctYW5kLXVybC1zdGF0ZS1tZW50YWwtbW9kZWwubWQ","note","notes\u002Freact\u002F10-routing-and-navigation\u002F01-routing-and-url-state-mental-model.md",{"id":495,"type":496,"sourcePath":497,"slug":499,"title":368,"updatedAt":21,"lastUpdated":21},"react\u002F10-routing-and-navigation\u002F01-routing-and-url-state-mental-model",{"type":501,"children":502},"root",[503,511,529,536,541,571,576,604,610,615,633,638,656,664,670,675,693,698,716,722,729,747,753,770,778,784,801,807,812,845,850,863,868,886,892,898,911,917,930,936,949,957,963,969,974,1027,1033,1037,1094,1099,1112,1118,1129,1137,1149,1165,1177,1190,1196,1250,1255],{"type":504,"tag":505,"props":506,"children":508},"element","h1",{"id":507},"路由与-url-state统一心智模型架构师视角",[509],{"type":510,"value":368},"text",{"type":504,"tag":512,"props":513,"children":514},"blockquote",{},[515],{"type":504,"tag":516,"props":517,"children":518},"p",{},[519,521,527],{"type":510,"value":520},"一句话结论：在中大型前端应用里，路由不只是“页面跳转”，它本质上是",{"type":504,"tag":522,"props":523,"children":524},"strong",{},[525],{"type":510,"value":526},"全局状态机 + 可回放的状态容器",{"type":510,"value":528},"——其中 URL（path + search + hash）是最可靠的“可分享\u002F可回退\u002F可重放”的状态载体；当你把“哪些状态应该进 URL”这件事定清楚，路由设计、数据预取、缓存命中、错误\u002F加载边界、以及导航性能都会变得可控。",{"type":504,"tag":530,"props":531,"children":533},"h2",{"id":532},"_1-为什么路由是架构问题而不是框架-api-问题",[534],{"type":510,"value":535},"1. 为什么路由是架构问题，而不是框架 API 问题？",{"type":504,"tag":516,"props":537,"children":538},{},[539],{"type":510,"value":540},"项目变复杂后，路由通常承载：",{"type":504,"tag":542,"props":543,"children":544},"ul",{},[545,551,556,561,566],{"type":504,"tag":546,"props":547,"children":548},"li",{},[549],{"type":510,"value":550},"信息架构：页面\u002F模块如何组织（目录结构、导航结构、权限结构）",{"type":504,"tag":546,"props":552,"children":553},{},[554],{"type":510,"value":555},"状态承载：筛选\u002F分页\u002F排序\u002F选中项\u002Ftab 是否需要回放",{"type":504,"tag":546,"props":557,"children":558},{},[559],{"type":510,"value":560},"数据获取：进入页面前是否要预取、如何避免瀑布",{"type":504,"tag":546,"props":562,"children":563},{},[564],{"type":510,"value":565},"体验治理：切页是否闪屏、是否保留旧 UI、骨架屏如何分层",{"type":504,"tag":546,"props":567,"children":568},{},[569],{"type":510,"value":570},"可靠性：404\u002F500\u002F鉴权失败\u002F局部模块错误怎么处理",{"type":504,"tag":516,"props":572,"children":573},{},[574],{"type":510,"value":575},"所以“路由怎么做”必须先回答 3 个架构问题：",{"type":504,"tag":577,"props":578,"children":579},"ol",{},[580,588,596],{"type":504,"tag":546,"props":581,"children":582},{},[583],{"type":504,"tag":522,"props":584,"children":585},{},[586],{"type":510,"value":587},"URL 是不是 source of truth？哪些状态要进 URL？",{"type":504,"tag":546,"props":589,"children":590},{},[591],{"type":504,"tag":522,"props":592,"children":593},{},[594],{"type":510,"value":595},"路由进入与数据获取的边界在哪里？（loader \u002F server fetch \u002F client fetch）",{"type":504,"tag":546,"props":597,"children":598},{},[599],{"type":504,"tag":522,"props":600,"children":601},{},[602],{"type":510,"value":603},"导航时 UI 体验策略是什么？（prefetch \u002F skeleton \u002F transition \u002F suspense）",{"type":504,"tag":530,"props":605,"children":607},{"id":606},"_2-url-state-是什么为什么它最重要",[608],{"type":510,"value":609},"2. URL State 是什么？为什么它最重要？",{"type":504,"tag":516,"props":611,"children":612},{},[613],{"type":510,"value":614},"URL State 指：为了满足以下任一需求，必须被编码进 URL 的状态：",{"type":504,"tag":542,"props":616,"children":617},{},[618,623,628],{"type":504,"tag":546,"props":619,"children":620},{},[621],{"type":510,"value":622},"可分享：复制链接给同事\u002F用户，打开后视图一致",{"type":504,"tag":546,"props":624,"children":625},{},[626],{"type":510,"value":627},"可回退：浏览器 back\u002Fforward 后视图一致",{"type":504,"tag":546,"props":629,"children":630},{},[631],{"type":510,"value":632},"可重放：刷新页面后视图一致（至少恢复到同一查询条件\u002F同一上下文）",{"type":504,"tag":516,"props":634,"children":635},{},[636],{"type":510,"value":637},"典型 URL state：",{"type":504,"tag":542,"props":639,"children":640},{},[641,646,651],{"type":504,"tag":546,"props":642,"children":643},{},[644],{"type":510,"value":645},"搜索关键字、筛选条件、分页、排序",{"type":504,"tag":546,"props":647,"children":648},{},[649],{"type":510,"value":650},"当前选中的 itemId（列表-详情联动）",{"type":504,"tag":546,"props":652,"children":653},{},[654],{"type":510,"value":655},"tab（如果它代表用户可分享的视图语义）",{"type":504,"tag":512,"props":657,"children":658},{},[659],{"type":504,"tag":516,"props":660,"children":661},{},[662],{"type":510,"value":663},"经验：只要它影响“用户看到的业务视图”，且用户会期望能通过链接还原，就应该考虑进 URL。",{"type":504,"tag":530,"props":665,"children":667},{"id":666},"_3-机制把路由当成状态机来设计",[668],{"type":510,"value":669},"3. 机制：把路由当成“状态机”来设计",{"type":504,"tag":516,"props":671,"children":672},{},[673],{"type":510,"value":674},"你可以用状态机视角理解路由：",{"type":504,"tag":542,"props":676,"children":677},{},[678,683,688],{"type":504,"tag":546,"props":679,"children":680},{},[681],{"type":510,"value":682},"state：当前 route（path params）+ search params + hash",{"type":504,"tag":546,"props":684,"children":685},{},[686],{"type":510,"value":687},"transition：navigate（push\u002Freplace\u002Fback\u002Fforward）",{"type":504,"tag":546,"props":689,"children":690},{},[691],{"type":510,"value":692},"side effects：数据预取、权限校验、埋点、滚动恢复",{"type":504,"tag":516,"props":694,"children":695},{},[696],{"type":510,"value":697},"当你用状态机思维审视路由，很多常见坑会自然消失：",{"type":504,"tag":542,"props":699,"children":700},{},[701,706,711],{"type":504,"tag":546,"props":702,"children":703},{},[704],{"type":510,"value":705},"“多源真相”问题：同一份筛选条件既在 store 又在 URL",{"type":504,"tag":546,"props":707,"children":708},{},[709],{"type":510,"value":710},"“不可回放”问题：用户 back 了但 UI 仍保持旧条件",{"type":504,"tag":546,"props":712,"children":713},{},[714],{"type":510,"value":715},"“刷新丢状态”问题：条件只存在内存",{"type":504,"tag":530,"props":717,"children":719},{"id":718},"_4-url-的三种信息path-params-search-params-hash",[720],{"type":510,"value":721},"4. URL 的三种信息：path params \u002F search params \u002F hash",{"type":504,"tag":723,"props":724,"children":726},"h3",{"id":725},"_41-path-params资源身份resource-identity",[727],{"type":510,"value":728},"4.1 path params：资源身份（resource identity）",{"type":504,"tag":542,"props":730,"children":731},{},[732,742],{"type":504,"tag":546,"props":733,"children":734},{},[735],{"type":504,"tag":736,"props":737,"children":739},"code",{"className":738},[],[740],{"type":510,"value":741},"\u002Fusers\u002F:userId",{"type":504,"tag":546,"props":743,"children":744},{},[745],{"type":510,"value":746},"通常表达“你在看哪个资源”",{"type":504,"tag":723,"props":748,"children":750},{"id":749},"_42-search-params视图投影view-projection",[751],{"type":510,"value":752},"4.2 search params：视图投影（view projection）",{"type":504,"tag":542,"props":754,"children":755},{},[756,765],{"type":504,"tag":546,"props":757,"children":758},{},[759],{"type":504,"tag":736,"props":760,"children":762},{"className":761},[],[763],{"type":510,"value":764},"?page=2&sort=xxx&keyword=abc",{"type":504,"tag":546,"props":766,"children":767},{},[768],{"type":510,"value":769},"通常表达“你以什么视角\u002F条件在看资源集合”",{"type":504,"tag":516,"props":771,"children":772},{},[773],{"type":504,"tag":522,"props":774,"children":775},{},[776],{"type":510,"value":777},"架构建议：筛选\u002F分页\u002F排序优先放 search params。",{"type":504,"tag":723,"props":779,"children":781},{"id":780},"_43-hash页面内定位锚点少量使用",[782],{"type":510,"value":783},"4.3 hash：页面内定位\u002F锚点（少量使用）",{"type":504,"tag":542,"props":785,"children":786},{},[787,796],{"type":504,"tag":546,"props":788,"children":789},{},[790],{"type":504,"tag":736,"props":791,"children":793},{"className":792},[],[794],{"type":510,"value":795},"#comments",{"type":504,"tag":546,"props":797,"children":798},{},[799],{"type":510,"value":800},"对 SPA 来说更多用于滚动定位；业务状态不要滥用 hash",{"type":504,"tag":530,"props":802,"children":804},{"id":803},"_5-路由与数据层的协作url-是条件真相query-是数据真相",[805],{"type":510,"value":806},"5. 路由与数据层的协作：URL 是条件真相，Query 是数据真相",{"type":504,"tag":516,"props":808,"children":809},{},[810],{"type":510,"value":811},"把上一章的数据层结论落到路由：",{"type":504,"tag":542,"props":813,"children":814},{},[815,826],{"type":504,"tag":546,"props":816,"children":817},{},[818,820],{"type":510,"value":819},"URL state（条件）：",{"type":504,"tag":736,"props":821,"children":823},{"className":822},[],[824],{"type":510,"value":825},"keyword\u002Fpage\u002Fsort\u002Ffilters",{"type":504,"tag":546,"props":827,"children":828},{},[829,831,837,839],{"type":510,"value":830},"Query cache（结果）：",{"type":504,"tag":736,"props":832,"children":834},{"className":833},[],[835],{"type":510,"value":836},"products list",{"type":510,"value":838}," \u002F ",{"type":504,"tag":736,"props":840,"children":842},{"className":841},[],[843],{"type":510,"value":844},"product detail",{"type":504,"tag":516,"props":846,"children":847},{},[848],{"type":510,"value":849},"正确姿势是：",{"type":504,"tag":577,"props":851,"children":852},{},[853,858],{"type":504,"tag":546,"props":854,"children":855},{},[856],{"type":510,"value":857},"URL 变化 → 派生 queryKey",{"type":504,"tag":546,"props":859,"children":860},{},[861],{"type":510,"value":862},"queryKey → 读取\u002F请求数据（TanStack Query 或 Next server fetch）",{"type":504,"tag":516,"props":864,"children":865},{},[866],{"type":510,"value":867},"这样保证：",{"type":504,"tag":542,"props":869,"children":870},{},[871,876,881],{"type":504,"tag":546,"props":872,"children":873},{},[874],{"type":510,"value":875},"同一 URL 必然命中同一缓存 key",{"type":504,"tag":546,"props":877,"children":878},{},[879],{"type":510,"value":880},"预取能命中",{"type":504,"tag":546,"props":882,"children":883},{},[884],{"type":510,"value":885},"back\u002Fforward 能回放",{"type":504,"tag":530,"props":887,"children":889},{"id":888},"_6-导航体验三件套prefetch-skeleton-transition",[890],{"type":510,"value":891},"6. 导航体验三件套：prefetch \u002F skeleton \u002F transition",{"type":504,"tag":723,"props":893,"children":895},{"id":894},"_61-prefetch把等待前移",[896],{"type":510,"value":897},"6.1 prefetch：把等待前移",{"type":504,"tag":542,"props":899,"children":900},{},[901,906],{"type":504,"tag":546,"props":902,"children":903},{},[904],{"type":510,"value":905},"hover 链接预取",{"type":504,"tag":546,"props":907,"children":908},{},[909],{"type":510,"value":910},"进入页面前预取（路由 loader \u002F server fetch）",{"type":504,"tag":723,"props":912,"children":914},{"id":913},"_62-skeleton把等待变可理解的占位",[915],{"type":510,"value":916},"6.2 skeleton：把等待变“可理解的占位”",{"type":504,"tag":542,"props":918,"children":919},{},[920,925],{"type":504,"tag":546,"props":921,"children":922},{},[923],{"type":510,"value":924},"route-level skeleton：页面壳",{"type":504,"tag":546,"props":926,"children":927},{},[928],{"type":510,"value":929},"section-level skeleton：列表区\u002F详情区",{"type":504,"tag":723,"props":931,"children":933},{"id":932},"_63-transition把非紧急更新降级尽量保留旧-ui",[934],{"type":510,"value":935},"6.3 transition：把非紧急更新降级，尽量保留旧 UI",{"type":504,"tag":542,"props":937,"children":938},{},[939,944],{"type":504,"tag":546,"props":940,"children":941},{},[942],{"type":510,"value":943},"切页\u002F筛选常常是 Transition 候选",{"type":504,"tag":546,"props":945,"children":946},{},[947],{"type":510,"value":948},"避免导航时频繁掉到 fallback（闪屏）",{"type":504,"tag":512,"props":950,"children":951},{},[952],{"type":504,"tag":516,"props":953,"children":954},{},[955],{"type":510,"value":956},"这三者分别解决：等待时间、视觉反馈、交互响应性。",{"type":504,"tag":530,"props":958,"children":960},{"id":959},"_7-两套技术栈下如何落地这套心智模型",[961],{"type":510,"value":962},"7. 两套技术栈下如何落地这套心智模型？",{"type":504,"tag":723,"props":964,"children":966},{"id":965},"_71-tanstack-router-vite客户端路由",[967],{"type":510,"value":968},"7.1 TanStack Router + Vite（客户端路由）",{"type":504,"tag":516,"props":970,"children":971},{},[972],{"type":510,"value":973},"落地要点：",{"type":504,"tag":542,"props":975,"children":976},{},[977,990,995],{"type":504,"tag":546,"props":978,"children":979},{},[980,982,988],{"type":510,"value":981},"URL state：用 ",{"type":504,"tag":736,"props":983,"children":985},{"className":984},[],[986],{"type":510,"value":987},"search params",{"type":510,"value":989}," 表达，并用 schema 定义默认值与类型（保证链接可还原）",{"type":504,"tag":546,"props":991,"children":992},{},[993],{"type":510,"value":994},"route loader：适合作为“进入页面前的准备阶段”（鉴权、prefetch）",{"type":504,"tag":546,"props":996,"children":997},{},[998,1000],{"type":510,"value":999},"与 TanStack Query 协作：\n",{"type":504,"tag":542,"props":1001,"children":1002},{},[1003,1014],{"type":504,"tag":546,"props":1004,"children":1005},{},[1006,1008],{"type":510,"value":1007},"loader 里 ",{"type":504,"tag":736,"props":1009,"children":1011},{"className":1010},[],[1012],{"type":510,"value":1013},"queryClient.prefetchQuery(queryKey)",{"type":504,"tag":546,"props":1015,"children":1016},{},[1017,1019,1025],{"type":510,"value":1018},"组件里 ",{"type":504,"tag":736,"props":1020,"children":1022},{"className":1021},[],[1023],{"type":510,"value":1024},"useQuery(queryKey)",{"type":510,"value":1026}," 直接命中",{"type":504,"tag":723,"props":1028,"children":1030},{"id":1029},"_72-nextjs-app-router全栈路由",[1031],{"type":510,"value":1032},"7.2 Next.js App Router（全栈路由）",{"type":504,"tag":516,"props":1034,"children":1035},{},[1036],{"type":510,"value":973},{"type":504,"tag":542,"props":1038,"children":1039},{},[1040,1053],{"type":504,"tag":546,"props":1041,"children":1042},{},[1043,1045,1051],{"type":510,"value":1044},"URL state：",{"type":504,"tag":736,"props":1046,"children":1048},{"className":1047},[],[1049],{"type":510,"value":1050},"searchParams",{"type":510,"value":1052}," 是天然的条件来源",{"type":504,"tag":546,"props":1054,"children":1055},{},[1056,1058],{"type":510,"value":1057},"segment 级边界：\n",{"type":504,"tag":542,"props":1059,"children":1060},{},[1061,1072,1083],{"type":504,"tag":546,"props":1062,"children":1063},{},[1064,1070],{"type":504,"tag":736,"props":1065,"children":1067},{"className":1066},[],[1068],{"type":510,"value":1069},"loading.tsx",{"type":510,"value":1071}," 负责“等”",{"type":504,"tag":546,"props":1073,"children":1074},{},[1075,1081],{"type":504,"tag":736,"props":1076,"children":1078},{"className":1077},[],[1079],{"type":510,"value":1080},"error.tsx",{"type":510,"value":1082}," 负责“错”",{"type":504,"tag":546,"props":1084,"children":1085},{},[1086,1092],{"type":504,"tag":736,"props":1087,"children":1089},{"className":1088},[],[1090],{"type":510,"value":1091},"not-found.tsx",{"type":510,"value":1093}," 负责“无”",{"type":504,"tag":516,"props":1095,"children":1096},{},[1097],{"type":510,"value":1098},"并且要把“数据在哪取”先定清：",{"type":504,"tag":542,"props":1100,"children":1101},{},[1102,1107],{"type":504,"tag":546,"props":1103,"children":1104},{},[1105],{"type":510,"value":1106},"Server Components 取数：更像框架级缓存与重验证（注意一致性策略）",{"type":504,"tag":546,"props":1108,"children":1109},{},[1110],{"type":510,"value":1111},"Client Components 取数：可用 TanStack Query 管理交互数据",{"type":504,"tag":530,"props":1113,"children":1115},{"id":1114},"_8-常见反模式",[1116],{"type":510,"value":1117},"8. 常见反模式",{"type":504,"tag":577,"props":1119,"children":1120},{},[1121],{"type":504,"tag":546,"props":1122,"children":1123},{},[1124],{"type":504,"tag":522,"props":1125,"children":1126},{},[1127],{"type":510,"value":1128},"把筛选条件复制到全局 store",{"type":504,"tag":542,"props":1130,"children":1131},{},[1132],{"type":504,"tag":546,"props":1133,"children":1134},{},[1135],{"type":510,"value":1136},"结果：URL 与 store 不一致；back\u002Fforward 不可回放；bug 难排",{"type":504,"tag":577,"props":1138,"children":1140},{"start":1139},2,[1141],{"type":504,"tag":546,"props":1142,"children":1143},{},[1144],{"type":504,"tag":522,"props":1145,"children":1146},{},[1147],{"type":510,"value":1148},"把“视图语义”塞进 path",{"type":504,"tag":542,"props":1150,"children":1151},{},[1152],{"type":504,"tag":546,"props":1153,"children":1154},{},[1155,1157,1163],{"type":510,"value":1156},"例如把 ",{"type":504,"tag":736,"props":1158,"children":1160},{"className":1159},[],[1161],{"type":510,"value":1162},"sort\u002Fpage\u002Ffilter",{"type":510,"value":1164}," 都做成 path 段，导致路由爆炸与维护困难",{"type":504,"tag":577,"props":1166,"children":1168},{"start":1167},3,[1169],{"type":504,"tag":546,"props":1170,"children":1171},{},[1172],{"type":504,"tag":522,"props":1173,"children":1174},{},[1175],{"type":510,"value":1176},"导航时整页 fallback（白屏）",{"type":504,"tag":542,"props":1178,"children":1179},{},[1180,1185],{"type":504,"tag":546,"props":1181,"children":1182},{},[1183],{"type":510,"value":1184},"结果：用户感知差；INP 变差",{"type":504,"tag":546,"props":1186,"children":1187},{},[1188],{"type":510,"value":1189},"解决：保持稳定 shell，切分 Suspense\u002FLoading 边界，必要时配合 Transition",{"type":504,"tag":530,"props":1191,"children":1193},{"id":1192},"_9-checklist你设计一个页面模块路由时自检",[1194],{"type":510,"value":1195},"9. Checklist（你设计一个页面\u002F模块路由时自检）",{"type":504,"tag":542,"props":1197,"children":1200},{"className":1198},[1199],"contains-task-list",[1201,1214,1223,1232,1241],{"type":504,"tag":546,"props":1202,"children":1205},{"className":1203},[1204],"task-list-item",[1206,1212],{"type":504,"tag":1207,"props":1208,"children":1211},"input",{"disabled":1209,"type":1210},true,"checkbox",[],{"type":510,"value":1213}," 哪些状态必须可分享\u002F可回放？是否进 URL？",{"type":504,"tag":546,"props":1215,"children":1217},{"className":1216},[1204],[1218,1221],{"type":504,"tag":1207,"props":1219,"children":1220},{"disabled":1209,"type":1210},[],{"type":510,"value":1222}," URL 中的 search params 是否有 schema\u002F默认值\u002F类型约束？（保证可还原）",{"type":504,"tag":546,"props":1224,"children":1226},{"className":1225},[1204],[1227,1230],{"type":504,"tag":1207,"props":1228,"children":1229},{"disabled":1209,"type":1210},[],{"type":510,"value":1231}," 数据获取边界在哪里？（loader \u002F server fetch \u002F client fetch）",{"type":504,"tag":546,"props":1233,"children":1235},{"className":1234},[1204],[1236,1239],{"type":504,"tag":1207,"props":1237,"children":1238},{"disabled":1209,"type":1210},[],{"type":510,"value":1240}," 是否有预取策略？是否能命中缓存？",{"type":504,"tag":546,"props":1242,"children":1244},{"className":1243},[1204],[1245,1248],{"type":504,"tag":1207,"props":1246,"children":1247},{"disabled":1209,"type":1210},[],{"type":510,"value":1249}," loading\u002Ferror\u002Fnot-found 是否分层？是否保持稳定 shell？",{"type":504,"tag":530,"props":1251,"children":1253},{"id":1252},"关联阅读",[1254],{"type":510,"value":1252},{"type":504,"tag":542,"props":1256,"children":1257},{},[1258,1273,1287],{"type":504,"tag":546,"props":1259,"children":1260},{},[1261,1263],{"type":510,"value":1262},"状态分层（URL state 的定位）：",{"type":504,"tag":1264,"props":1265,"children":1267},"a",{"href":1266},"..\u002F11-data-layer\u002F01-state-layering-ui-server-url-global.md",[1268],{"type":504,"tag":736,"props":1269,"children":1271},{"className":1270},[],[1272],{"type":510,"value":1266},{"type":504,"tag":546,"props":1274,"children":1275},{},[1276,1278],{"type":510,"value":1277},"TanStack Query 缓存与失效：",{"type":504,"tag":1264,"props":1279,"children":1281},{"href":1280},"..\u002F11-data-layer\u002F02-tanstack-query-caching-and-invalidation.md",[1282],{"type":504,"tag":736,"props":1283,"children":1285},{"className":1284},[],[1286],{"type":510,"value":1280},{"type":504,"tag":546,"props":1288,"children":1289},{},[1290,1292],{"type":510,"value":1291},"Transition（导航\u002F筛选的体验治理）：",{"type":504,"tag":1264,"props":1293,"children":1295},{"href":1294},"..\u002F09-react-18-in-practice\u002F03-transition-useTransition-useDeferredValue.md",[1296],{"type":504,"tag":736,"props":1297,"children":1299},{"className":1298},[],[1300],{"type":510,"value":1294},{"title":1302,"searchDepth":1139,"depth":1139,"links":1303},"",[1304,1305,1306,1307,1312,1313,1318,1322,1323,1324],{"id":532,"depth":1139,"text":535},{"id":606,"depth":1139,"text":609},{"id":666,"depth":1139,"text":669},{"id":718,"depth":1139,"text":721,"children":1308},[1309,1310,1311],{"id":725,"depth":1167,"text":728},{"id":749,"depth":1167,"text":752},{"id":780,"depth":1167,"text":783},{"id":803,"depth":1139,"text":806},{"id":888,"depth":1139,"text":891,"children":1314},[1315,1316,1317],{"id":894,"depth":1167,"text":897},{"id":913,"depth":1167,"text":916},{"id":932,"depth":1167,"text":935},{"id":959,"depth":1139,"text":962,"children":1319},[1320,1321],{"id":965,"depth":1167,"text":968},{"id":1029,"depth":1167,"text":1032},{"id":1114,"depth":1139,"text":1117},{"id":1192,"depth":1139,"text":1195},{"id":1252,"depth":1139,"text":1252},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1326},"\u003Cpath fill=\"currentColor\" d=\"m10.828 12l4.95 4.95l-1.414 1.415L8 12l6.364-6.364l1.414 1.414z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1328},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm0 7h12v2H3zm0 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":1330},"\u003Cpath fill=\"currentColor\" d=\"m13.172 12l-4.95-4.95l1.414-1.413L16 12l-6.364 6.364l-1.414-1.415z\"\u002F>"]