[{"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\u002F02-tanstack-router-route-tree-search-loader-prefetch":494,"i-ri:arrow-left-s-line":2060,"i-ri:menu-2-line":2062,"i-ri:arrow-right-s-line":2064,"i-ep:copy-document":2066},{"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":371,"path":371,"title":372,"updatedAt":21,"meta":498,"body":500,"toc":2038},"bm90ZTpub3Rlcy9yZWFjdC8xMC1yb3V0aW5nLWFuZC1uYXZpZ2F0aW9uLzAyLXRhbnN0YWNrLXJvdXRlci1yb3V0ZS10cmVlLXNlYXJjaC1sb2FkZXItcHJlZmV0Y2gubWQ","note","notes\u002Freact\u002F10-routing-and-navigation\u002F02-tanstack-router-route-tree-search-loader-prefetch.md",{"id":495,"type":496,"sourcePath":497,"slug":499,"title":372,"updatedAt":21,"lastUpdated":21},"react\u002F10-routing-and-navigation\u002F02-tanstack-router-route-tree-search-loader-prefetch",{"type":501,"children":502},"root",[503,511,538,545,550,585,593,599,606,611,630,636,688,693,729,735,741,746,781,789,795,800,1144,1149,1169,1177,1183,1189,1194,1217,1222,1228,1233,1260,1265,1580,1585,1710,1715,1733,1739,1744,1762,1768,1792,1798,1816,1821,1827,1838,1846,1857,1870,1881,1889,1900,1908,1914,1967,1972,2032],{"type":504,"tag":505,"props":506,"children":508},"element","h1",{"id":507},"tanstack-routervite-sparoute-tree-search-loader-prefetch落地篇",[509],{"type":510,"value":372},"text",{"type":504,"tag":512,"props":513,"children":514},"blockquote",{},[515],{"type":504,"tag":516,"props":517,"children":518},"p",{},[519,521,527,529,536],{"type":510,"value":520},"一句话结论：TanStack Router 的价值不在于“能跳转”，而在于它把路由变成",{"type":504,"tag":522,"props":523,"children":524},"strong",{},[525],{"type":510,"value":526},"强类型的 route tree（信息架构）+ 可校验的 search params（URL State）+ 可组合的 loader\u002FbeforeLoad（进入页面前的副作用边界）",{"type":510,"value":528},"；当你把它与 TanStack Query 的 ",{"type":504,"tag":530,"props":531,"children":533},"code",{"className":532},[],[534],{"type":510,"value":535},"queryKey",{"type":510,"value":537}," 对齐，就能得到一套可预取、可回放、可观测的导航与数据系统。",{"type":504,"tag":539,"props":540,"children":542},"h2",{"id":541},"_0-你应该先确定的-3-个架构问题",[543],{"type":510,"value":544},"0. 你应该先确定的 3 个架构问题",{"type":504,"tag":516,"props":546,"children":547},{},[548],{"type":510,"value":549},"在写代码前，先用架构语言把问题定清：",{"type":504,"tag":551,"props":552,"children":553},"ol",{},[554,565,575],{"type":504,"tag":555,"props":556,"children":557},"li",{},[558,563],{"type":504,"tag":522,"props":559,"children":560},{},[561],{"type":510,"value":562},"哪些状态要进 URL（search params）？",{"type":510,"value":564},"（可分享\u002F可回退\u002F可重放）",{"type":504,"tag":555,"props":566,"children":567},{},[568,573],{"type":504,"tag":522,"props":569,"children":570},{},[571],{"type":510,"value":572},"进入页面前要做什么？",{"type":510,"value":574},"（鉴权 \u002F 预取 \u002F 参数校验 \u002F 埋点）这些副作用放在哪一层？",{"type":504,"tag":555,"props":576,"children":577},{},[578,583],{"type":504,"tag":522,"props":579,"children":580},{},[581],{"type":510,"value":582},"数据缓存系统是谁？",{"type":510,"value":584},"（通常是 TanStack Query）路由层只负责“条件与边界”，不要重复造缓存。",{"type":504,"tag":512,"props":586,"children":587},{},[588],{"type":504,"tag":516,"props":589,"children":590},{},[591],{"type":510,"value":592},"这 3 个问题如果没先定清，路由会很快变成“到处 useEffect + 到处同步”的泥潭。",{"type":504,"tag":539,"props":594,"children":596},{"id":595},"_1-route-tree把信息架构做成可维护的树",[597],{"type":510,"value":598},"1. Route Tree：把信息架构做成“可维护的树”",{"type":504,"tag":600,"props":601,"children":603},"h3",{"id":602},"_11-route-tree-的意义",[604],{"type":510,"value":605},"1.1 Route Tree 的意义",{"type":504,"tag":516,"props":607,"children":608},{},[609],{"type":510,"value":610},"Route Tree 不是形式主义，它直接决定：",{"type":504,"tag":612,"props":613,"children":614},"ul",{},[615,620,625],{"type":504,"tag":555,"props":616,"children":617},{},[618],{"type":510,"value":619},"layout\u002Fshell 如何复用（哪些页面共享导航栏\u002F侧边栏\u002F权限边界）",{"type":504,"tag":555,"props":621,"children":622},{},[623],{"type":510,"value":624},"URL 结构是否稳定（SEO\u002F分享\u002F可读性）",{"type":504,"tag":555,"props":626,"children":627},{},[628],{"type":510,"value":629},"权限\u002F埋点\u002F错误边界能否在“路由级”统一",{"type":504,"tag":600,"props":631,"children":633},{"id":632},"_12-tanstack-router-的常见组织方式概念",[634],{"type":510,"value":635},"1.2 TanStack Router 的常见组织方式（概念）",{"type":504,"tag":612,"props":637,"children":638},{},[639,650,661],{"type":504,"tag":555,"props":640,"children":641},{},[642,648],{"type":504,"tag":530,"props":643,"children":645},{"className":644},[],[646],{"type":510,"value":647},"rootRoute",{"type":510,"value":649},"：应用壳（全局 layout、全局错误边界、全局 context）",{"type":504,"tag":555,"props":651,"children":652},{},[653,659],{"type":504,"tag":530,"props":654,"children":656},{"className":655},[],[657],{"type":510,"value":658},"indexRoute",{"type":510,"value":660},"：默认子路由",{"type":504,"tag":555,"props":662,"children":663},{},[664,670,672,678,680,686],{"type":504,"tag":530,"props":665,"children":667},{"className":666},[],[668],{"type":510,"value":669},"segment routes",{"type":510,"value":671},"：按业务域拆分（例如 ",{"type":504,"tag":530,"props":673,"children":675},{"className":674},[],[676],{"type":510,"value":677},"\u002Forders\u002F*",{"type":510,"value":679},"、",{"type":504,"tag":530,"props":681,"children":683},{"className":682},[],[684],{"type":510,"value":685},"\u002Fusers\u002F*",{"type":510,"value":687},"）",{"type":504,"tag":516,"props":689,"children":690},{},[691],{"type":510,"value":692},"工程建议：",{"type":504,"tag":612,"props":694,"children":695},{},[696,706],{"type":504,"tag":555,"props":697,"children":698},{},[699,704],{"type":504,"tag":522,"props":700,"children":701},{},[702],{"type":510,"value":703},"按业务域拆 route modules",{"type":510,"value":705},"，不要把所有路由写一个文件",{"type":504,"tag":555,"props":707,"children":708},{},[709,711],{"type":510,"value":710},"在 route module 内维护该域的：\n",{"type":504,"tag":612,"props":712,"children":713},{},[714,719,724],{"type":504,"tag":555,"props":715,"children":716},{},[717],{"type":510,"value":718},"search schema（URL state）",{"type":504,"tag":555,"props":720,"children":721},{},[722],{"type":510,"value":723},"loader（prefetch\u002F鉴权）",{"type":504,"tag":555,"props":725,"children":726},{},[727],{"type":510,"value":728},"与 Query key 对齐的 queryOptions",{"type":504,"tag":539,"props":730,"children":732},{"id":731},"_2-search-paramsurl-state-的类型系统与默认值系统",[733],{"type":510,"value":734},"2. Search Params：URL State 的“类型系统与默认值系统”",{"type":504,"tag":600,"props":736,"children":738},{"id":737},"_21-为什么-search-params-必须-schema-化",[739],{"type":510,"value":740},"2.1 为什么 search params 必须 schema 化？",{"type":504,"tag":516,"props":742,"children":743},{},[744],{"type":510,"value":745},"在真实项目里，如果 search params 不做 schema：",{"type":504,"tag":612,"props":747,"children":748},{},[749,760,765,776],{"type":504,"tag":555,"props":750,"children":751},{},[752,758],{"type":504,"tag":530,"props":753,"children":755},{"className":754},[],[756],{"type":510,"value":757},"page",{"type":510,"value":759}," 是 string 还是 number？",{"type":504,"tag":555,"props":761,"children":762},{},[763],{"type":510,"value":764},"缺省时默认是 1 还是 0？",{"type":504,"tag":555,"props":766,"children":767},{},[768,774],{"type":504,"tag":530,"props":769,"children":771},{"className":770},[],[772],{"type":510,"value":773},"sort",{"type":510,"value":775}," 出现未知枚举值怎么办？",{"type":504,"tag":555,"props":777,"children":778},{},[779],{"type":510,"value":780},"用户手改 URL 导致页面崩溃怎么办？",{"type":504,"tag":516,"props":782,"children":783},{},[784],{"type":504,"tag":522,"props":785,"children":786},{},[787],{"type":510,"value":788},"结论：search params 必须是“可校验 + 可默认 + 可序列化”的。",{"type":504,"tag":600,"props":790,"children":792},{"id":791},"_22-推荐模式用-schema-定义-url-state",[793],{"type":510,"value":794},"2.2 推荐模式：用 schema 定义 URL state",{"type":504,"tag":516,"props":796,"children":797},{},[798],{"type":510,"value":799},"伪代码示意（重点是模式，不强依赖某个 schema 库）：",{"type":504,"tag":801,"props":802,"children":807},"pre",{"className":803,"code":804,"language":805,"meta":806,"style":806},"language-ts shiki shiki-themes github-light github-dark","\u002F\u002F 以 zod 为例（也可以 valibot \u002F arkType \u002F 自己写 parser）\nimport { z } from 'zod'\n\nexport const productsSearchSchema = z.object({\n  keyword: z.string().optional().default(''),\n  page: z.coerce.number().int().min(1).default(1),\n  sort: z.enum(['relevance', 'price_asc', 'price_desc']).default('relevance'),\n})\n\nexport type ProductsSearch = z.infer\u003Ctypeof productsSearchSchema>\n","ts","",[808],{"type":504,"tag":530,"props":809,"children":810},{"__ignoreMap":806},[811,823,850,860,901,949,1011,1075,1084,1092],{"type":504,"tag":812,"props":813,"children":816},"span",{"class":814,"line":815},"line",1,[817],{"type":504,"tag":812,"props":818,"children":820},{"style":819},"--shiki-default:#6A737D;--shiki-dark:#6A737D",[821],{"type":510,"value":822},"\u002F\u002F 以 zod 为例（也可以 valibot \u002F arkType \u002F 自己写 parser）\n",{"type":504,"tag":812,"props":824,"children":826},{"class":814,"line":825},2,[827,833,839,844],{"type":504,"tag":812,"props":828,"children":830},{"style":829},"--shiki-default:#D73A49;--shiki-dark:#F97583",[831],{"type":510,"value":832},"import",{"type":504,"tag":812,"props":834,"children":836},{"style":835},"--shiki-default:#24292E;--shiki-dark:#E1E4E8",[837],{"type":510,"value":838}," { z } ",{"type":504,"tag":812,"props":840,"children":841},{"style":829},[842],{"type":510,"value":843},"from",{"type":504,"tag":812,"props":845,"children":847},{"style":846},"--shiki-default:#032F62;--shiki-dark:#9ECBFF",[848],{"type":510,"value":849}," 'zod'\n",{"type":504,"tag":812,"props":851,"children":853},{"class":814,"line":852},3,[854],{"type":504,"tag":812,"props":855,"children":857},{"emptyLinePlaceholder":856},true,[858],{"type":510,"value":859},"\n",{"type":504,"tag":812,"props":861,"children":863},{"class":814,"line":862},4,[864,869,874,880,885,890,896],{"type":504,"tag":812,"props":865,"children":866},{"style":829},[867],{"type":510,"value":868},"export",{"type":504,"tag":812,"props":870,"children":871},{"style":829},[872],{"type":510,"value":873}," const",{"type":504,"tag":812,"props":875,"children":877},{"style":876},"--shiki-default:#005CC5;--shiki-dark:#79B8FF",[878],{"type":510,"value":879}," productsSearchSchema",{"type":504,"tag":812,"props":881,"children":882},{"style":829},[883],{"type":510,"value":884}," =",{"type":504,"tag":812,"props":886,"children":887},{"style":835},[888],{"type":510,"value":889}," z.",{"type":504,"tag":812,"props":891,"children":893},{"style":892},"--shiki-default:#6F42C1;--shiki-dark:#B392F0",[894],{"type":510,"value":895},"object",{"type":504,"tag":812,"props":897,"children":898},{"style":835},[899],{"type":510,"value":900},"({\n",{"type":504,"tag":812,"props":902,"children":904},{"class":814,"line":903},5,[905,910,915,920,925,929,934,939,944],{"type":504,"tag":812,"props":906,"children":907},{"style":835},[908],{"type":510,"value":909},"  keyword: z.",{"type":504,"tag":812,"props":911,"children":912},{"style":892},[913],{"type":510,"value":914},"string",{"type":504,"tag":812,"props":916,"children":917},{"style":835},[918],{"type":510,"value":919},"().",{"type":504,"tag":812,"props":921,"children":922},{"style":892},[923],{"type":510,"value":924},"optional",{"type":504,"tag":812,"props":926,"children":927},{"style":835},[928],{"type":510,"value":919},{"type":504,"tag":812,"props":930,"children":931},{"style":892},[932],{"type":510,"value":933},"default",{"type":504,"tag":812,"props":935,"children":936},{"style":835},[937],{"type":510,"value":938},"(",{"type":504,"tag":812,"props":940,"children":941},{"style":846},[942],{"type":510,"value":943},"''",{"type":504,"tag":812,"props":945,"children":946},{"style":835},[947],{"type":510,"value":948},"),\n",{"type":504,"tag":812,"props":950,"children":952},{"class":814,"line":951},6,[953,958,963,967,972,976,981,985,990,995,999,1003,1007],{"type":504,"tag":812,"props":954,"children":955},{"style":835},[956],{"type":510,"value":957},"  page: z.coerce.",{"type":504,"tag":812,"props":959,"children":960},{"style":892},[961],{"type":510,"value":962},"number",{"type":504,"tag":812,"props":964,"children":965},{"style":835},[966],{"type":510,"value":919},{"type":504,"tag":812,"props":968,"children":969},{"style":892},[970],{"type":510,"value":971},"int",{"type":504,"tag":812,"props":973,"children":974},{"style":835},[975],{"type":510,"value":919},{"type":504,"tag":812,"props":977,"children":978},{"style":892},[979],{"type":510,"value":980},"min",{"type":504,"tag":812,"props":982,"children":983},{"style":835},[984],{"type":510,"value":938},{"type":504,"tag":812,"props":986,"children":987},{"style":876},[988],{"type":510,"value":989},"1",{"type":504,"tag":812,"props":991,"children":992},{"style":835},[993],{"type":510,"value":994},").",{"type":504,"tag":812,"props":996,"children":997},{"style":892},[998],{"type":510,"value":933},{"type":504,"tag":812,"props":1000,"children":1001},{"style":835},[1002],{"type":510,"value":938},{"type":504,"tag":812,"props":1004,"children":1005},{"style":876},[1006],{"type":510,"value":989},{"type":504,"tag":812,"props":1008,"children":1009},{"style":835},[1010],{"type":510,"value":948},{"type":504,"tag":812,"props":1012,"children":1014},{"class":814,"line":1013},7,[1015,1020,1025,1030,1035,1040,1045,1049,1054,1059,1063,1067,1071],{"type":504,"tag":812,"props":1016,"children":1017},{"style":835},[1018],{"type":510,"value":1019},"  sort: z.",{"type":504,"tag":812,"props":1021,"children":1022},{"style":892},[1023],{"type":510,"value":1024},"enum",{"type":504,"tag":812,"props":1026,"children":1027},{"style":835},[1028],{"type":510,"value":1029},"([",{"type":504,"tag":812,"props":1031,"children":1032},{"style":846},[1033],{"type":510,"value":1034},"'relevance'",{"type":504,"tag":812,"props":1036,"children":1037},{"style":835},[1038],{"type":510,"value":1039},", ",{"type":504,"tag":812,"props":1041,"children":1042},{"style":846},[1043],{"type":510,"value":1044},"'price_asc'",{"type":504,"tag":812,"props":1046,"children":1047},{"style":835},[1048],{"type":510,"value":1039},{"type":504,"tag":812,"props":1050,"children":1051},{"style":846},[1052],{"type":510,"value":1053},"'price_desc'",{"type":504,"tag":812,"props":1055,"children":1056},{"style":835},[1057],{"type":510,"value":1058},"]).",{"type":504,"tag":812,"props":1060,"children":1061},{"style":892},[1062],{"type":510,"value":933},{"type":504,"tag":812,"props":1064,"children":1065},{"style":835},[1066],{"type":510,"value":938},{"type":504,"tag":812,"props":1068,"children":1069},{"style":846},[1070],{"type":510,"value":1034},{"type":504,"tag":812,"props":1072,"children":1073},{"style":835},[1074],{"type":510,"value":948},{"type":504,"tag":812,"props":1076,"children":1078},{"class":814,"line":1077},8,[1079],{"type":504,"tag":812,"props":1080,"children":1081},{"style":835},[1082],{"type":510,"value":1083},"})\n",{"type":504,"tag":812,"props":1085,"children":1087},{"class":814,"line":1086},9,[1088],{"type":504,"tag":812,"props":1089,"children":1090},{"emptyLinePlaceholder":856},[1091],{"type":510,"value":859},{"type":504,"tag":812,"props":1093,"children":1095},{"class":814,"line":1094},10,[1096,1100,1105,1110,1114,1119,1124,1129,1134,1139],{"type":504,"tag":812,"props":1097,"children":1098},{"style":829},[1099],{"type":510,"value":868},{"type":504,"tag":812,"props":1101,"children":1102},{"style":829},[1103],{"type":510,"value":1104}," type",{"type":504,"tag":812,"props":1106,"children":1107},{"style":892},[1108],{"type":510,"value":1109}," ProductsSearch",{"type":504,"tag":812,"props":1111,"children":1112},{"style":829},[1113],{"type":510,"value":884},{"type":504,"tag":812,"props":1115,"children":1116},{"style":892},[1117],{"type":510,"value":1118}," z",{"type":504,"tag":812,"props":1120,"children":1121},{"style":835},[1122],{"type":510,"value":1123},".",{"type":504,"tag":812,"props":1125,"children":1126},{"style":892},[1127],{"type":510,"value":1128},"infer",{"type":504,"tag":812,"props":1130,"children":1131},{"style":835},[1132],{"type":510,"value":1133},"\u003C",{"type":504,"tag":812,"props":1135,"children":1136},{"style":829},[1137],{"type":510,"value":1138},"typeof",{"type":504,"tag":812,"props":1140,"children":1141},{"style":835},[1142],{"type":510,"value":1143}," productsSearchSchema>\n",{"type":504,"tag":516,"props":1145,"children":1146},{},[1147],{"type":510,"value":1148},"配合路由：",{"type":504,"tag":612,"props":1150,"children":1151},{},[1152,1157],{"type":504,"tag":555,"props":1153,"children":1154},{},[1155],{"type":510,"value":1156},"URL 缺字段 → 自动补默认值",{"type":504,"tag":555,"props":1158,"children":1159},{},[1160,1162,1168],{"type":510,"value":1161},"URL 字段类型不对 → 统一纠正\u002F兜底（而不是组件里到处 ",{"type":504,"tag":530,"props":1163,"children":1165},{"className":1164},[],[1166],{"type":510,"value":1167},"Number()",{"type":510,"value":687},{"type":504,"tag":512,"props":1170,"children":1171},{},[1172],{"type":504,"tag":516,"props":1173,"children":1174},{},[1175],{"type":510,"value":1176},"这一步做对了，你的“可分享\u002F可回退\u002F可回放”能力才算真正成立。",{"type":504,"tag":539,"props":1178,"children":1180},{"id":1179},"_3-loader-beforeload进入页面前的副作用边界",[1181],{"type":510,"value":1182},"3. Loader \u002F beforeLoad：进入页面前的“副作用边界”",{"type":504,"tag":600,"props":1184,"children":1186},{"id":1185},"_31-为什么需要-loader",[1187],{"type":510,"value":1188},"3.1 为什么需要 loader？",{"type":504,"tag":516,"props":1190,"children":1191},{},[1192],{"type":510,"value":1193},"loader（或 beforeLoad）用于承载：",{"type":504,"tag":612,"props":1195,"children":1196},{},[1197,1202,1207,1212],{"type":504,"tag":555,"props":1198,"children":1199},{},[1200],{"type":510,"value":1201},"参数校验（search\u002Fschema）",{"type":504,"tag":555,"props":1203,"children":1204},{},[1205],{"type":510,"value":1206},"鉴权（没权限就 redirect）",{"type":504,"tag":555,"props":1208,"children":1209},{},[1210],{"type":510,"value":1211},"数据预取（prefetch）",{"type":504,"tag":555,"props":1213,"children":1214},{},[1215],{"type":510,"value":1216},"进入页面前的埋点（route view）",{"type":504,"tag":516,"props":1218,"children":1219},{},[1220],{"type":510,"value":1221},"它的核心价值是：把这些逻辑从组件的 useEffect 中抽离出来，变成“路由生命周期的一部分”。",{"type":504,"tag":600,"props":1223,"children":1225},{"id":1224},"_32-与-tanstack-query-的协作loader-做-prefetch组件做-usequery",[1226],{"type":510,"value":1227},"3.2 与 TanStack Query 的协作：loader 做 prefetch，组件做 useQuery",{"type":504,"tag":516,"props":1229,"children":1230},{},[1231],{"type":510,"value":1232},"推荐做法：",{"type":504,"tag":551,"props":1234,"children":1235},{},[1236,1247],{"type":504,"tag":555,"props":1237,"children":1238},{},[1239,1241],{"type":510,"value":1240},"route loader 里：",{"type":504,"tag":530,"props":1242,"children":1244},{"className":1243},[],[1245],{"type":510,"value":1246},"queryClient.prefetchQuery(queryOptions)",{"type":504,"tag":555,"props":1248,"children":1249},{},[1250,1252,1258],{"type":510,"value":1251},"页面组件里：",{"type":504,"tag":530,"props":1253,"children":1255},{"className":1254},[],[1256],{"type":510,"value":1257},"useQuery(queryOptions)",{"type":510,"value":1259}," 直接命中缓存",{"type":504,"tag":516,"props":1261,"children":1262},{},[1263],{"type":510,"value":1264},"示意：",{"type":504,"tag":801,"props":1266,"children":1268},{"className":803,"code":1267,"language":805,"meta":806,"style":806},"\u002F\u002F products.route.ts\nimport { queryOptions } from '@tanstack\u002Freact-query'\n\nexport const productsQueryOptions = (search: ProductsSearch) =>\n  queryOptions({\n    queryKey: ['products', search],\n    queryFn: () => api.products.list(search),\n  })\n\nexport const route = new Route({\n  \u002F\u002F ...\n  loader: async ({ context, search }) => {\n    await context.queryClient.prefetchQuery(productsQueryOptions(search))\n  },\n})\n",[1269],{"type":504,"tag":530,"props":1270,"children":1271},{"__ignoreMap":806},[1272,1280,1301,1308,1358,1370,1388,1421,1429,1436,1470,1479,1530,1563,1572],{"type":504,"tag":812,"props":1273,"children":1274},{"class":814,"line":815},[1275],{"type":504,"tag":812,"props":1276,"children":1277},{"style":819},[1278],{"type":510,"value":1279},"\u002F\u002F products.route.ts\n",{"type":504,"tag":812,"props":1281,"children":1282},{"class":814,"line":825},[1283,1287,1292,1296],{"type":504,"tag":812,"props":1284,"children":1285},{"style":829},[1286],{"type":510,"value":832},{"type":504,"tag":812,"props":1288,"children":1289},{"style":835},[1290],{"type":510,"value":1291}," { queryOptions } ",{"type":504,"tag":812,"props":1293,"children":1294},{"style":829},[1295],{"type":510,"value":843},{"type":504,"tag":812,"props":1297,"children":1298},{"style":846},[1299],{"type":510,"value":1300}," '@tanstack\u002Freact-query'\n",{"type":504,"tag":812,"props":1302,"children":1303},{"class":814,"line":852},[1304],{"type":504,"tag":812,"props":1305,"children":1306},{"emptyLinePlaceholder":856},[1307],{"type":510,"value":859},{"type":504,"tag":812,"props":1309,"children":1310},{"class":814,"line":862},[1311,1315,1319,1324,1328,1333,1339,1344,1348,1353],{"type":504,"tag":812,"props":1312,"children":1313},{"style":829},[1314],{"type":510,"value":868},{"type":504,"tag":812,"props":1316,"children":1317},{"style":829},[1318],{"type":510,"value":873},{"type":504,"tag":812,"props":1320,"children":1321},{"style":892},[1322],{"type":510,"value":1323}," productsQueryOptions",{"type":504,"tag":812,"props":1325,"children":1326},{"style":829},[1327],{"type":510,"value":884},{"type":504,"tag":812,"props":1329,"children":1330},{"style":835},[1331],{"type":510,"value":1332}," (",{"type":504,"tag":812,"props":1334,"children":1336},{"style":1335},"--shiki-default:#E36209;--shiki-dark:#FFAB70",[1337],{"type":510,"value":1338},"search",{"type":504,"tag":812,"props":1340,"children":1341},{"style":829},[1342],{"type":510,"value":1343},":",{"type":504,"tag":812,"props":1345,"children":1346},{"style":892},[1347],{"type":510,"value":1109},{"type":504,"tag":812,"props":1349,"children":1350},{"style":835},[1351],{"type":510,"value":1352},") ",{"type":504,"tag":812,"props":1354,"children":1355},{"style":829},[1356],{"type":510,"value":1357},"=>\n",{"type":504,"tag":812,"props":1359,"children":1360},{"class":814,"line":903},[1361,1366],{"type":504,"tag":812,"props":1362,"children":1363},{"style":892},[1364],{"type":510,"value":1365},"  queryOptions",{"type":504,"tag":812,"props":1367,"children":1368},{"style":835},[1369],{"type":510,"value":900},{"type":504,"tag":812,"props":1371,"children":1372},{"class":814,"line":951},[1373,1378,1383],{"type":504,"tag":812,"props":1374,"children":1375},{"style":835},[1376],{"type":510,"value":1377},"    queryKey: [",{"type":504,"tag":812,"props":1379,"children":1380},{"style":846},[1381],{"type":510,"value":1382},"'products'",{"type":504,"tag":812,"props":1384,"children":1385},{"style":835},[1386],{"type":510,"value":1387},", search],\n",{"type":504,"tag":812,"props":1389,"children":1390},{"class":814,"line":1013},[1391,1396,1401,1406,1411,1416],{"type":504,"tag":812,"props":1392,"children":1393},{"style":892},[1394],{"type":510,"value":1395},"    queryFn",{"type":504,"tag":812,"props":1397,"children":1398},{"style":835},[1399],{"type":510,"value":1400},": () ",{"type":504,"tag":812,"props":1402,"children":1403},{"style":829},[1404],{"type":510,"value":1405},"=>",{"type":504,"tag":812,"props":1407,"children":1408},{"style":835},[1409],{"type":510,"value":1410}," api.products.",{"type":504,"tag":812,"props":1412,"children":1413},{"style":892},[1414],{"type":510,"value":1415},"list",{"type":504,"tag":812,"props":1417,"children":1418},{"style":835},[1419],{"type":510,"value":1420},"(search),\n",{"type":504,"tag":812,"props":1422,"children":1423},{"class":814,"line":1077},[1424],{"type":504,"tag":812,"props":1425,"children":1426},{"style":835},[1427],{"type":510,"value":1428},"  })\n",{"type":504,"tag":812,"props":1430,"children":1431},{"class":814,"line":1086},[1432],{"type":504,"tag":812,"props":1433,"children":1434},{"emptyLinePlaceholder":856},[1435],{"type":510,"value":859},{"type":504,"tag":812,"props":1437,"children":1438},{"class":814,"line":1094},[1439,1443,1447,1452,1456,1461,1466],{"type":504,"tag":812,"props":1440,"children":1441},{"style":829},[1442],{"type":510,"value":868},{"type":504,"tag":812,"props":1444,"children":1445},{"style":829},[1446],{"type":510,"value":873},{"type":504,"tag":812,"props":1448,"children":1449},{"style":876},[1450],{"type":510,"value":1451}," route",{"type":504,"tag":812,"props":1453,"children":1454},{"style":829},[1455],{"type":510,"value":884},{"type":504,"tag":812,"props":1457,"children":1458},{"style":829},[1459],{"type":510,"value":1460}," new",{"type":504,"tag":812,"props":1462,"children":1463},{"style":892},[1464],{"type":510,"value":1465}," Route",{"type":504,"tag":812,"props":1467,"children":1468},{"style":835},[1469],{"type":510,"value":900},{"type":504,"tag":812,"props":1471,"children":1473},{"class":814,"line":1472},11,[1474],{"type":504,"tag":812,"props":1475,"children":1476},{"style":819},[1477],{"type":510,"value":1478},"  \u002F\u002F ...\n",{"type":504,"tag":812,"props":1480,"children":1482},{"class":814,"line":1481},12,[1483,1488,1493,1498,1503,1508,1512,1516,1521,1525],{"type":504,"tag":812,"props":1484,"children":1485},{"style":892},[1486],{"type":510,"value":1487},"  loader",{"type":504,"tag":812,"props":1489,"children":1490},{"style":835},[1491],{"type":510,"value":1492},": ",{"type":504,"tag":812,"props":1494,"children":1495},{"style":829},[1496],{"type":510,"value":1497},"async",{"type":504,"tag":812,"props":1499,"children":1500},{"style":835},[1501],{"type":510,"value":1502}," ({ ",{"type":504,"tag":812,"props":1504,"children":1505},{"style":1335},[1506],{"type":510,"value":1507},"context",{"type":504,"tag":812,"props":1509,"children":1510},{"style":835},[1511],{"type":510,"value":1039},{"type":504,"tag":812,"props":1513,"children":1514},{"style":1335},[1515],{"type":510,"value":1338},{"type":504,"tag":812,"props":1517,"children":1518},{"style":835},[1519],{"type":510,"value":1520}," }) ",{"type":504,"tag":812,"props":1522,"children":1523},{"style":829},[1524],{"type":510,"value":1405},{"type":504,"tag":812,"props":1526,"children":1527},{"style":835},[1528],{"type":510,"value":1529}," {\n",{"type":504,"tag":812,"props":1531,"children":1533},{"class":814,"line":1532},13,[1534,1539,1544,1549,1553,1558],{"type":504,"tag":812,"props":1535,"children":1536},{"style":829},[1537],{"type":510,"value":1538},"    await",{"type":504,"tag":812,"props":1540,"children":1541},{"style":835},[1542],{"type":510,"value":1543}," context.queryClient.",{"type":504,"tag":812,"props":1545,"children":1546},{"style":892},[1547],{"type":510,"value":1548},"prefetchQuery",{"type":504,"tag":812,"props":1550,"children":1551},{"style":835},[1552],{"type":510,"value":938},{"type":504,"tag":812,"props":1554,"children":1555},{"style":892},[1556],{"type":510,"value":1557},"productsQueryOptions",{"type":504,"tag":812,"props":1559,"children":1560},{"style":835},[1561],{"type":510,"value":1562},"(search))\n",{"type":504,"tag":812,"props":1564,"children":1566},{"class":814,"line":1565},14,[1567],{"type":504,"tag":812,"props":1568,"children":1569},{"style":835},[1570],{"type":510,"value":1571},"  },\n",{"type":504,"tag":812,"props":1573,"children":1575},{"class":814,"line":1574},15,[1576],{"type":504,"tag":812,"props":1577,"children":1578},{"style":835},[1579],{"type":510,"value":1083},{"type":504,"tag":516,"props":1581,"children":1582},{},[1583],{"type":510,"value":1584},"页面：",{"type":504,"tag":801,"props":1586,"children":1588},{"className":803,"code":1587,"language":805,"meta":806,"style":806},"function ProductsPage() {\n  const search = Route.useSearch()\n  const { data, isLoading } = useQuery(productsQueryOptions(search))\n  \u002F\u002F ...\n}\n",[1589],{"type":504,"tag":530,"props":1590,"children":1591},{"__ignoreMap":806},[1592,1610,1642,1695,1702],{"type":504,"tag":812,"props":1593,"children":1594},{"class":814,"line":815},[1595,1600,1605],{"type":504,"tag":812,"props":1596,"children":1597},{"style":829},[1598],{"type":510,"value":1599},"function",{"type":504,"tag":812,"props":1601,"children":1602},{"style":892},[1603],{"type":510,"value":1604}," ProductsPage",{"type":504,"tag":812,"props":1606,"children":1607},{"style":835},[1608],{"type":510,"value":1609},"() {\n",{"type":504,"tag":812,"props":1611,"children":1612},{"class":814,"line":825},[1613,1618,1623,1627,1632,1637],{"type":504,"tag":812,"props":1614,"children":1615},{"style":829},[1616],{"type":510,"value":1617},"  const",{"type":504,"tag":812,"props":1619,"children":1620},{"style":876},[1621],{"type":510,"value":1622}," search",{"type":504,"tag":812,"props":1624,"children":1625},{"style":829},[1626],{"type":510,"value":884},{"type":504,"tag":812,"props":1628,"children":1629},{"style":835},[1630],{"type":510,"value":1631}," Route.",{"type":504,"tag":812,"props":1633,"children":1634},{"style":892},[1635],{"type":510,"value":1636},"useSearch",{"type":504,"tag":812,"props":1638,"children":1639},{"style":835},[1640],{"type":510,"value":1641},"()\n",{"type":504,"tag":812,"props":1643,"children":1644},{"class":814,"line":852},[1645,1649,1654,1659,1663,1668,1673,1678,1683,1687,1691],{"type":504,"tag":812,"props":1646,"children":1647},{"style":829},[1648],{"type":510,"value":1617},{"type":504,"tag":812,"props":1650,"children":1651},{"style":835},[1652],{"type":510,"value":1653}," { ",{"type":504,"tag":812,"props":1655,"children":1656},{"style":876},[1657],{"type":510,"value":1658},"data",{"type":504,"tag":812,"props":1660,"children":1661},{"style":835},[1662],{"type":510,"value":1039},{"type":504,"tag":812,"props":1664,"children":1665},{"style":876},[1666],{"type":510,"value":1667},"isLoading",{"type":504,"tag":812,"props":1669,"children":1670},{"style":835},[1671],{"type":510,"value":1672}," } ",{"type":504,"tag":812,"props":1674,"children":1675},{"style":829},[1676],{"type":510,"value":1677},"=",{"type":504,"tag":812,"props":1679,"children":1680},{"style":892},[1681],{"type":510,"value":1682}," useQuery",{"type":504,"tag":812,"props":1684,"children":1685},{"style":835},[1686],{"type":510,"value":938},{"type":504,"tag":812,"props":1688,"children":1689},{"style":892},[1690],{"type":510,"value":1557},{"type":504,"tag":812,"props":1692,"children":1693},{"style":835},[1694],{"type":510,"value":1562},{"type":504,"tag":812,"props":1696,"children":1697},{"class":814,"line":862},[1698],{"type":504,"tag":812,"props":1699,"children":1700},{"style":819},[1701],{"type":510,"value":1478},{"type":504,"tag":812,"props":1703,"children":1704},{"class":814,"line":903},[1705],{"type":504,"tag":812,"props":1706,"children":1707},{"style":835},[1708],{"type":510,"value":1709},"}\n",{"type":504,"tag":516,"props":1711,"children":1712},{},[1713],{"type":510,"value":1714},"关键约束：",{"type":504,"tag":612,"props":1716,"children":1717},{},[1718,1728],{"type":504,"tag":555,"props":1719,"children":1720},{},[1721,1726],{"type":504,"tag":522,"props":1722,"children":1723},{},[1724],{"type":510,"value":1725},"prefetch 与 useQuery 必须复用同一套 queryKey",{"type":510,"value":1727},"，否则预取不命中",{"type":504,"tag":555,"props":1729,"children":1730},{},[1731],{"type":510,"value":1732},"search（URL state）是 queryKey 的输入真相，避免多源同步",{"type":504,"tag":539,"props":1734,"children":1736},{"id":1735},"_4-prefetch导航性能治理的预算系统",[1737],{"type":510,"value":1738},"4. Prefetch：导航性能治理的“预算系统”",{"type":504,"tag":516,"props":1740,"children":1741},{},[1742],{"type":510,"value":1743},"Prefetch 不是越多越好，它需要预算：",{"type":504,"tag":612,"props":1745,"children":1746},{},[1747,1752,1757],{"type":504,"tag":555,"props":1748,"children":1749},{},[1750],{"type":510,"value":1751},"hover 预取：适合详情页、小数据",{"type":504,"tag":555,"props":1753,"children":1754},{},[1755],{"type":510,"value":1756},"进入页面前预取：适合主列表（命中率高）",{"type":504,"tag":555,"props":1758,"children":1759},{},[1760],{"type":510,"value":1761},"低网速\u002F移动端：要降低预取量（避免把带宽打满）",{"type":504,"tag":600,"props":1763,"children":1765},{"id":1764},"_41-常见预取点位",[1766],{"type":510,"value":1767},"4.1 常见预取点位",{"type":504,"tag":612,"props":1769,"children":1770},{},[1771,1782,1787],{"type":504,"tag":555,"props":1772,"children":1773},{},[1774,1780],{"type":504,"tag":530,"props":1775,"children":1777},{"className":1776},[],[1778],{"type":510,"value":1779},"Link",{"type":510,"value":1781}," hover \u002F intent：预取下一个路由的 loader",{"type":504,"tag":555,"props":1783,"children":1784},{},[1785],{"type":510,"value":1786},"进入列表页：预取首屏数据",{"type":504,"tag":555,"props":1788,"children":1789},{},[1790],{"type":510,"value":1791},"列表渲染时：对“首屏可见区域”的详情做轻量预取（谨慎）",{"type":504,"tag":600,"props":1793,"children":1795},{"id":1794},"_42-预取与体验配合-transitionsuspense",[1796],{"type":510,"value":1797},"4.2 预取与体验：配合 Transition\u002FSuspense",{"type":504,"tag":612,"props":1799,"children":1800},{},[1801,1806,1811],{"type":504,"tag":555,"props":1802,"children":1803},{},[1804],{"type":510,"value":1805},"预取解决“更快拿到数据”",{"type":504,"tag":555,"props":1807,"children":1808},{},[1809],{"type":510,"value":1810},"Transition 解决“切换时保持交互响应、尽量保留旧 UI”",{"type":504,"tag":555,"props":1812,"children":1813},{},[1814],{"type":510,"value":1815},"Loading\u002FSkeleton 解决“拿不到数据时的视觉反馈”",{"type":504,"tag":516,"props":1817,"children":1818},{},[1819],{"type":510,"value":1820},"你应该把它们当成一套组合拳，而不是单点优化。",{"type":504,"tag":539,"props":1822,"children":1824},{"id":1823},"_5-常见坑强烈建议对照自检",[1825],{"type":510,"value":1826},"5. 常见坑（强烈建议对照自检）",{"type":504,"tag":551,"props":1828,"children":1829},{},[1830],{"type":504,"tag":555,"props":1831,"children":1832},{},[1833],{"type":504,"tag":522,"props":1834,"children":1835},{},[1836],{"type":510,"value":1837},"search params 不做 schema",{"type":504,"tag":612,"props":1839,"children":1840},{},[1841],{"type":504,"tag":555,"props":1842,"children":1843},{},[1844],{"type":510,"value":1845},"后果：默认值散落各处、类型错乱、URL 可回放性崩溃",{"type":504,"tag":551,"props":1847,"children":1848},{"start":825},[1849],{"type":504,"tag":555,"props":1850,"children":1851},{},[1852],{"type":504,"tag":522,"props":1853,"children":1854},{},[1855],{"type":510,"value":1856},"loader 里直接 setState \u002F 操作 UI",{"type":504,"tag":612,"props":1858,"children":1859},{},[1860,1865],{"type":504,"tag":555,"props":1861,"children":1862},{},[1863],{"type":510,"value":1864},"后果：路由层与视图层耦合，难以测试与复用",{"type":504,"tag":555,"props":1866,"children":1867},{},[1868],{"type":510,"value":1869},"建议：loader 只做“准备与约束”，视图由组件渲染",{"type":504,"tag":551,"props":1871,"children":1872},{"start":852},[1873],{"type":504,"tag":555,"props":1874,"children":1875},{},[1876],{"type":504,"tag":522,"props":1877,"children":1878},{},[1879],{"type":510,"value":1880},"prefetch 的 queryKey 与 useQuery 不一致",{"type":504,"tag":612,"props":1882,"children":1883},{},[1884],{"type":504,"tag":555,"props":1885,"children":1886},{},[1887],{"type":510,"value":1888},"后果：明明预取了却没命中，性能优化白做",{"type":504,"tag":551,"props":1890,"children":1891},{"start":862},[1892],{"type":504,"tag":555,"props":1893,"children":1894},{},[1895],{"type":504,"tag":522,"props":1896,"children":1897},{},[1898],{"type":510,"value":1899},"把 URL state 复制到全局 store",{"type":504,"tag":612,"props":1901,"children":1902},{},[1903],{"type":504,"tag":555,"props":1904,"children":1905},{},[1906],{"type":510,"value":1907},"后果：back\u002Fforward 不可回放，状态同步复杂度爆炸",{"type":504,"tag":539,"props":1909,"children":1911},{"id":1910},"_6-checklist",[1912],{"type":510,"value":1913},"6. Checklist",{"type":504,"tag":612,"props":1915,"children":1918},{"className":1916},[1917],"contains-task-list",[1919,1931,1940,1949,1958],{"type":504,"tag":555,"props":1920,"children":1923},{"className":1921},[1922],"task-list-item",[1924,1929],{"type":504,"tag":1925,"props":1926,"children":1928},"input",{"disabled":856,"type":1927},"checkbox",[],{"type":510,"value":1930}," 是否为所有 search params 定义 schema（类型 + 默认值 + 兜底）？",{"type":504,"tag":555,"props":1932,"children":1934},{"className":1933},[1922],[1935,1938],{"type":504,"tag":1925,"props":1936,"children":1937},{"disabled":856,"type":1927},[],{"type":510,"value":1939}," URL state 是否是筛选\u002F分页\u002F排序的唯一真相？",{"type":504,"tag":555,"props":1941,"children":1943},{"className":1942},[1922],[1944,1947],{"type":504,"tag":1925,"props":1945,"children":1946},{"disabled":856,"type":1927},[],{"type":510,"value":1948}," loader\u002FbeforeLoad 是否只承载“进入页面前的约束与准备”（鉴权\u002F预取\u002F埋点）？",{"type":504,"tag":555,"props":1950,"children":1952},{"className":1951},[1922],[1953,1956],{"type":504,"tag":1925,"props":1954,"children":1955},{"disabled":856,"type":1927},[],{"type":510,"value":1957}," prefetch 是否有预算（命中率、网络、设备）？",{"type":504,"tag":555,"props":1959,"children":1961},{"className":1960},[1922],[1962,1965],{"type":504,"tag":1925,"props":1963,"children":1964},{"disabled":856,"type":1927},[],{"type":510,"value":1966}," queryKey 是否稳定、可序列化，并且与 URL state 对齐？",{"type":504,"tag":539,"props":1968,"children":1970},{"id":1969},"关联阅读",[1971],{"type":510,"value":1969},{"type":504,"tag":612,"props":1973,"children":1974},{},[1975,1990,2004,2018],{"type":504,"tag":555,"props":1976,"children":1977},{},[1978,1980],{"type":510,"value":1979},"路由与 URL state 心智模型：",{"type":504,"tag":1981,"props":1982,"children":1984},"a",{"href":1983},".\u002F01-routing-and-url-state-mental-model.md",[1985],{"type":504,"tag":530,"props":1986,"children":1988},{"className":1987},[],[1989],{"type":510,"value":1983},{"type":504,"tag":555,"props":1991,"children":1992},{},[1993,1995],{"type":510,"value":1994},"状态分层（URL\u002FServer state 边界）：",{"type":504,"tag":1981,"props":1996,"children":1998},{"href":1997},"..\u002F11-data-layer\u002F01-state-layering-ui-server-url-global.md",[1999],{"type":504,"tag":530,"props":2000,"children":2002},{"className":2001},[],[2003],{"type":510,"value":1997},{"type":504,"tag":555,"props":2005,"children":2006},{},[2007,2009],{"type":510,"value":2008},"TanStack Query 缓存与失效：",{"type":504,"tag":1981,"props":2010,"children":2012},{"href":2011},"..\u002F11-data-layer\u002F02-tanstack-query-caching-and-invalidation.md",[2013],{"type":504,"tag":530,"props":2014,"children":2016},{"className":2015},[],[2017],{"type":510,"value":2011},{"type":504,"tag":555,"props":2019,"children":2020},{},[2021,2023],{"type":510,"value":2022},"Transition（导航体验治理）：",{"type":504,"tag":1981,"props":2024,"children":2026},{"href":2025},"..\u002F09-react-18-in-practice\u002F03-transition-useTransition-useDeferredValue.md",[2027],{"type":504,"tag":530,"props":2028,"children":2030},{"className":2029},[],[2031],{"type":510,"value":2025},{"type":504,"tag":2033,"props":2034,"children":2035},"style",{},[2036],{"type":510,"value":2037},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":806,"searchDepth":825,"depth":825,"links":2039},[2040,2041,2045,2049,2053,2057,2058,2059],{"id":541,"depth":825,"text":544},{"id":595,"depth":825,"text":598,"children":2042},[2043,2044],{"id":602,"depth":852,"text":605},{"id":632,"depth":852,"text":635},{"id":731,"depth":825,"text":734,"children":2046},[2047,2048],{"id":737,"depth":852,"text":740},{"id":791,"depth":852,"text":794},{"id":1179,"depth":825,"text":1182,"children":2050},[2051,2052],{"id":1185,"depth":852,"text":1188},{"id":1224,"depth":852,"text":1227},{"id":1735,"depth":825,"text":1738,"children":2054},[2055,2056],{"id":1764,"depth":852,"text":1767},{"id":1794,"depth":852,"text":1797},{"id":1823,"depth":825,"text":1826},{"id":1910,"depth":825,"text":1913},{"id":1969,"depth":825,"text":1969},{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":2061},"\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":2063},"\u003Cpath fill=\"currentColor\" d=\"M3 4h18v2H3zm0 7h12v2H3zm0 7h18v2H3z\"\u002F>",{"left":4,"top":4,"width":5,"height":5,"rotate":4,"vFlip":6,"hFlip":6,"body":2065},"\u003Cpath fill=\"currentColor\" d=\"m13.172 12l-4.95-4.95l1.414-1.413L16 12l-6.364 6.364l-1.414-1.415z\"\u002F>",{"left":4,"top":4,"width":2067,"height":2067,"rotate":4,"vFlip":6,"hFlip":6,"body":2068},1024,"\u003Cpath fill=\"currentColor\" d=\"M768 832a128 128 0 0 1-128 128H192A128 128 0 0 1 64 832V384a128 128 0 0 1 128-128v64a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64z\"\u002F>\u003Cpath fill=\"currentColor\" d=\"M384 128a64 64 0 0 0-64 64v448a64 64 0 0 0 64 64h448a64 64 0 0 0 64-64V192a64 64 0 0 0-64-64zm0-64h448a128 128 0 0 1 128 128v448a128 128 0 0 1-128 128H384a128 128 0 0 1-128-128V192A128 128 0 0 1 384 64\"\u002F>"]