ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AI全栈实战 | 2.2-02 React 思维模型:数据不可变 vs Vue 数据可变,两种哲学把复杂度推给谁

AI全栈实战 | 2.2-02 React 思维模型:数据不可变 vs Vue 数据可变,两种哲学把复杂度推给谁 上篇回顾2.2-01 拆解了 Vue3 的 Proxy 响应式、组合式 API、组件通信、双向绑定本质。本篇讲 React——前端另一大框架。对后端工程师来说React 的心智模型比 Vue 陡峭得多JSX Hooks 不可变数据但理解 React 能让你形成「为什么同样的需求两种框架设计完全不同」的判断力。一、开篇同一个需求Vue 和 React 两种写法需求一个计数器点击 1显示当前值。Vue3template button clickcount{{ count }}/button /template script setup import { ref } from vue; const count ref(0); /scriptReactimport { useState } from react; function Counter() { const [count, setCount] useState(0); return button onClick{() setCount(count 1)}{count}/button; }表面看差不多但底层哲学截然不同Vuecount直接修改数据响应式自动更新 UIReactsetCount(count 1)创建新值触发重新渲染不能直接修改 count这就是本篇的核心命题数据可变 vs 数据不可变两种哲学各自把复杂度推给了谁。二、JSXHTML in JavaScript2.1 JSX 是什么JSX 不是 HTML是 JavaScript 的语法扩展const element h1 classNametitleHello/h1;编译后变成constelementReact.createElement(h1,{className:title},Hello);所以 JSX 本质是createElement的语法糖。2.2 与 Vue 模板的区别维度Vue 模板JSX语言HTML 扩展v-if/v-forJavaScript 表达式灵活度受限模板语法完全灵活JS 能力学习曲线低像 HTML中要懂 JS类型检查弱强TS 友好Vue 模板把逻辑限制在模板语法内JSX 把模板融入 JS。各有优劣——Vue 对新手友好JSX 对高级用户灵活。三、虚拟 DOM 与 diff 策略3.1 为什么需要虚拟 DOM直接操作真实 DOM 很慢重排重绘。虚拟 DOM 是一棵 JS 对象树修改时先改虚拟 DOM再 diff 出最小变化批量更新真实 DOM。// 虚拟 DOM 节点{type:div,props:{className:box},children:[{type:span,props:{},children:[Hello]}]}3.2 diff 算法的三个假设不同类型节点 → 直接替换div 变 span整个子树重建同类型节点 → 复用 DOM更新属性列表 diff → 用 key 标识key 相同复用不同销毁重建3.3 key 的重要性// 没 keyReact 按位置 diff可能错乱 items.map(item li{item.text}/li); // 有 keyReact 按 key diff精准匹配 items.map(item li key{item.id}{item.text}/li);不要用 index 做 key——列表中间插入/删除时index 变化导致 React 误判性能差且可能 bug。3.4 Vue 和 React 的虚拟 DOM 一样吗底层思路一样diff 最小更新但Vue2全量 diffVue3编译时标记静态节点diff 时跳过PatchFlagReactFiber 架构可中断 diff时间分片四、Hooks函数式组件的状态4.1 React 的函数式理念React 推崇函数式编程组件是纯函数输入 props 输出 UI。但纯函数没有状态——Hooks 就是给函数组件加状态的「钩子」。function Counter() { const [count, setCount] useState(0); // 状态钩子 return button onClick{() setCount(count 1)}{count}/button; }4.2 useState 的正确理解const[count,setCount]useState(0);count当前值不可变不能countsetCount触发更新的函数0初始值setCount做两件事更新内部状态创建新值不修改旧的触发组件重新渲染4.3 useEffect副作用钩子function UserList() { const [users, setUsers] useState([]); useEffect(() { fetch(/api/users) .then(res res.json()) .then(data setUsers(data)); }, []); // 空依赖数组只在挂载时执行一次 return ul{users.map(u li key{u.id}{u.name}/li)}/ul; }useEffect的依赖数组不传每次渲染后都执行[]只在挂载时执行[dep1, dep2]dep 变化时执行4.4 依赖数组的陷阱useEffect(() { fetch(/api/user/${userId}) .then(setUser); }, [userId]);如果忘了加userId到依赖数组userId 变了但 effect 不重新执行——数据不更新。这是 React 最常见的 bug 之一。ESLint 的react-hooks/exhaustive-deps规则会自动检测这个问题。五、数据不可变React 的核心原则5.1 为什么不能直接修改// 错误直接修改 state const [list, setList] useState([1, 2, 3]); list.push(4); setList(list); // React 不会重新渲染React 用Object.is比较新旧 state引用相同就跳过渲染。list.push没改引用React 认为没变。// 正确创建新数组 setList([...list, 4]); // 新引用触发渲染5.2 不可变数据的哲学React 的核心理念数据不可变immutable。每次修改都创建新值旧值不变。好处时间旅行undo/redo旧状态还在性能优化引用比较比深比较快并发安全不可变数据天然线程安全代价内存开销每次创建新对象心智负担要记住不能直接改5.3 Vue 的可变哲学conststatereactive({list:[1,2,3]});state.list.push(4);// 直接修改响应式触发Vue 用 Proxy 拦截修改知道你改了什么。不需要创建新对象。5.4 两种哲学把复杂度推给谁哲学复杂度推给优势React 不可变开发者要手动创建新值性能优化简单引用比较Vue 可变框架Proxy 拦截要追踪所有修改开发者心智负担小结论React 把数据管理的复杂度推给开发者换性能优化的简单Vue 把复杂度吞进框架换开发体验的简洁。没有对错看团队偏好。六、受控组件 vs 非受控组件6.1 受控组件function Form() { const [text, setText] useState(); return input value{text} onChange{e setText(e.target.value)} /; }输入框的值由 React state 控制。每次输入都触发 setState → 重新渲染。6.2 非受控组件function Form() { const inputRef useRef(); return input ref{inputRef} defaultValue /; }输入框的值由 DOM 自己管React 通过 ref 读取。推荐表单用受控组件数据在 React 里便于校验和提交简单场景用非受控性能好。七、Vue vs React 选型对比维度Vue3React心智模型可变数据 响应式不可变数据 重新渲染模板模板语法JSX状态ref/reactiveuseState/useReducer副作用watch/watchEffectuseEffect生态国内中后台强国际化、跨平台TS 支持好Vue3 重写极好JSX 天然适配学习曲线平缓陡峭适合场景管理后台、中后台复杂交互、React Native后端转前端推荐 Vue3但理解 React 能让你明白「为什么有不同的设计选择」。八、小结表概念ReactVue 对照视图描述JSX模板状态useStateref/reactive数据原则不可变可变副作用useEffectwatchEffect性能优化引用比较Proxy 追踪列表 key必须必须
返回列表