摘要(Auto)

  • 生成时间:2025-12-20
  • 简历中出现的项目标题(提取):大疆用户中心重构 / 大疆售后 RMS 系统重构 / 跨平台公告插件系统 / 大疆 DevOps 平台维护 / XDR 系统 - 魔方大屏 + 报表
  • 面试大纲关键词(提取 Top10):1)大疆用户中心重构:性能优化 + HTTP 原理 + Webpack 架构 / 性能指标与方法论 / 简历可落地点(结合你的“优化四板斧”) / HTTP 常考点(从“为什么变快”倒推) / Webpack 架构(工程化面试常考) / 按优化顺序,把方案“串起来”(排查 → 定位 → 选择 → 验证) / 0. 排查与基线(先把问题“量化”) / 1. 先保“可见”——骨架屏预渲染(直接拉低 LCP) / 2. 再减“阻塞”——关键渲染路径(CRP)梳理:CSS/字体/首图优先级 / 3. 再降“下载与解析成本”——更小的包体与更少的无效代码

建议追问(Auto)

  • 你为什么在该项目/场景里选择这个方案?替代方案为何不选?
  • 最大一次事故/踩坑是什么?如何定位与回滚?
  • 如果重做:架构/边界/工程化会怎么调整?

关联卡片

在我项目中的角色与使用场景

  • 用户中心 / 中后台复杂表单:关注“渲染性能 + 可维护性”,避免组件树失控导致的频繁重渲染与状态错乱。
  • 大屏/报表:关注“高频更新 + 大量可视化组件”,重点治理长任务、列表/图表渲染与内存增长。
  • 我负责的落地:
    • 组件分层(容器/展示/领域组件)、状态归属(本地/全局/服务端缓存)与边界约束。
    • 性能治理:渲染链路定位、memo 策略、虚拟列表、分片渲染、事件与订阅收敛。
    • 工程实践:错误边界、日志上报、可观测性埋点与“可回滚”的发布策略。

原理简述

React 的关键能力可以用“声明式 UI + 可预测更新 + 可组合抽象”来概括。

  • 声明式:你描述“状态 → UI”的映射,React 负责把变化映射到 DOM 更新。
  • Diff/Reconciliation:通过对比前后两棵虚拟树,找出最小更新集(关键是“同层比较 + key 决定身份”)。
  • Fiber(React 16+):把渲染拆成可中断/可恢复的工作单元(work),为并发与优先级调度提供基础。
  • 并发特性(React 18)
    • 自动批处理(batching)减少无意义的多次 render。
    • startTransition 把“非紧急更新”降级,提升交互响应。
    • Suspense 让数据/代码加载可以用一致的“等待边界”表达。

性能的核心心智:

  • render 不是坏事,“无效 render” 才是问题(render 频率、render 成本、commit 成本)。
  • 优化顺序:先定位(Profiler/Performance)→ 再缩小影响面(状态归属/订阅)→ 再降成本(memo/虚拟化/分片)。

对比表格

维度ReactVueSvelte
核心模型声明式 + 组件组合模板 + 响应式编译期消解框架运行时
性能手段Fiber/并发、memo、虚拟化响应式依赖追踪编译输出更贴近原生
工程生态最丰富(状态/路由/组件库/测试)完整、上手快生态相对小
适用场景中大型应用、团队协作复杂中小到中大型均可对体积/性能极致且可控场景
风险点心智复杂(hooks/并发/性能)模板约束/TS 体验差异生态与招聘面更窄

在我面试表达里的“决策口径”:

  • 团队与存量决定上限:已有 React 生态 + 组件资产,React 是最稳的选择。
  • 若重点是“把性能治理体系做起来”,React 需要更强的边界与规范(状态归属、渲染订阅、memo 策略)。

模拟问答

  • [ ] Q1:为什么 key 不能用 index?什么时候可以用?
    • 结论:当列表会插入/删除/排序时,index 会让 React 误判“身份”,导致状态错位与额外 DOM 操作。
    • 可以用的例外:静态列表(不会增删改顺序)且无局部状态依赖。
  • [ ] Q2:useEffect 为什么会“执行两次”?怎么解释给面试官?
    • React 18 开发模式下 StrictMode 会对部分副作用做“额外调用”以暴露不纯副作用(生产不会)。
    • 正确做法:把副作用写成幂等,或把“仅一次初始化”移动到更合理的抽象(例如上层状态、服务端缓存层)。
  • [ ] Q3:你怎么定位并解决“无效渲染”?
    • 定位:React Profiler 看 commit 次数与耗时;再用 why-did-you-render/自定义日志定位触发源。
    • 处理顺序:状态下沉/拆分 context → 订阅收敛(selector)→ memo/useMemo/useCallback → 虚拟列表/分片渲染。
  • [ ] Q4:startTransition 解决的是什么问题?怎么用?
    • 把“非紧急的 UI 更新”标注为 transition,让紧急交互(输入/点击反馈)优先。

手写代码区

一个“可解释”的渲染订阅收敛示例(用 useSyncExternalStore 表达“按需订阅”):

import { useSyncExternalStore } from 'react'

type State = { count: number; text: string }
let state: State = { count: 0, text: '' }
const listeners = new Set<() => void>()

export function setState(patch: Partial<State>) {
  state = { ...state, ...patch }
  listeners.forEach((l) => l())
}

function subscribe(listener: () => void) {
  listeners.add(listener)
  return () => listeners.delete(listener)
}

function getSnapshot() {
  return state
}

export function useStoreSelector<T>(selector: (s: State) => T) {
  const snap = useSyncExternalStore(subscribe, getSnapshot, getSnapshot)
  return selector(snap)
}

// 用法:组件只订阅自己需要的字段,减少无效渲染
// const count = useStoreSelector((s) => s.count);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

我的补充(Manual)

(不会被脚本覆盖:踩坑、细节、反例、排查路径)

复盘与反思(Learnings)

  • 如果重做会怎么改?

面试官追问(面试官视角)

  • [ ] 为什么选这个方案?替代方案为什么不选?
  • [!] 最大一次事故/踩坑是什么?如何定位与回滚?
  • [ ] 如果重做会怎么改?
上次更新:
(adsbygoogle = window.adsbygoogle || []).push({});