1.React是什么

用于构建用户界面(UI)的开源 Js库, 将数据渲染成html视图; 最初由 Facebook(现 Meta)开发并维护,旨在提供一种高效、灵活且可重用的 UI 组件开发方式。

核心工作原理与特性

  • 组件化架(Component-based):React 将复杂的页面拆分为独立、可复用的“组件”(如按钮、导航栏、整个页面)。每个组件都包含自己的逻辑和外观,这使得代码更加模块化、易于维护。

  • 虚拟 DOM(Virtual DOM):这是 React 高效的关键。当组件的状态发生变化时,React 会先在内存中更新轻量级的“虚拟 DOM”,然后与真实的 DOM 进行对比(Diff 算法),最后只将发生变化的部分更新到真实页面上,从而极大地减少了浏览器的重绘开销,提升了性能。

  • 声明式设计与单向数据流:React 采用声明式范式,开发者只需描述界面“应该长什么样”,当数据变化时界面会自动更新。同时,它遵循单向数据流(通过 props 从父组件向子组件传递数据),保证了数据的可控性和可预测性。

关键语法与开发模式

  • JSX 语法:开发者在 js中直接编写类似 HTML 的结构。这打破了传统前端将结构与逻辑分离的做法,让渲染逻辑和内容展示维护在同一个地方,开发更加直观。

  • React Hooks:Hooks(如 useStateuseEffect)是 React 的重大创新,它允许开发者在不编写类(Class)的情况下,在函数组件中使用状态管理和其他 React 特性,大幅简化了代码结构。

  • 服务端组件(Server Components):较新的特性,允许组件仅在服务器端运行,有助于实现前后端工作分离,进一步提升应用性能和数据获取能力。

生态系统与跨平台能力

  • 丰富的生态:React 拥有极其庞大的社区和第三方库支持,开发者可以方便地集成路由、状态管理等工具,灵活选择适合自己项目的技术栈。

  • 跨平台开发:除了用于构建 Web 单页应用(SPA),React 的设计思想还衍生出了 React Native,允许开发者使用类似 React 的语法来开发 iOS 和 Android 原生移动应用,实现“一次学习,多端开发”。

React对比Vue

1. 核心语法与设计哲学

  • React:定位为“UI 库”,推崇极致的灵活性。它采用 JSX 语法,将 HTML 结构与 JavaScript 逻辑写在同一个文件中,要求开发者具备较强的函数式编程思维。React 采用单向数据流和不可变数据设计,状态变更需要手动调用 setState 或 useState 的 setter 函数来显式触发重渲染。

  • Vue:定位为“渐进式框架”,追求“自动高效”。它采用 Template(模板)语法,将 HTML、JS 和 CSS 分离在单文件组件中,对传统前端开发者非常友好。Vue 拥有强大的响应式系统(基于 Proxy),能够自动追踪数据依赖,数据变化时视图会自动更新,且支持双向数据绑定(v-model)。

2. 底层原理与渲染性能

  • React:采用 虚拟 DOM + Fiber 架构。当状态更新时,React 会重新执行组件函数生成新的虚拟 DOM 树,通过 Diff 算法计算最小变更。其 Fiber 架构支持并发渲染,可以将渲染任务拆分为小单元并支持中断,在处理复杂交互和高频更新时能提供极其流畅的用户体验。

  • Vue:同样采用虚拟 DOM,但结合了编译时优化。Vue 的模板编译器在构建阶段会进行静态分析(如静态提升、PatchFlag 靶向更新),跳过不必要的对比。此外,Vue 3 引入的 Vapor Mode 更是能将模板直接编译为极高效的命令式 DOM 操作指令,实现元素级精准更新,在中小型应用中性能表现极为出色。

3. 学习曲线与开发体验

  • Vue:学习曲线平缓,上手极快。官方提供了“全家桶”(Vue Router、Pinia 等),开箱即用,开发者无需在技术选型上花费大量时间,适合快速原型开发和中小型项目。

  • React:学习曲线较陡。由于 React 本身只是一个视图库,开发者需要自行在庞大的社区中挑选路由、状态管理(如 Redux、Zustand)等第三方库,并深入理解 Hooks 规则、闭包等 JavaScript 底层概念。适合大型复杂应用、高交互性产品

2.创建项目

使用vite创建:

npm create vite@latest my-react-app -- --template react

使用webpack创建:

npx create-react-app my-react-app

cd my-react-app

npm install

npm run dev

3.hooks

React Hooks是 React 16.8 引入的新特性,允许开发者在不编写类组件的情况下,在函数组件中使用state和其他 React 特性。简化了代码结构,提升了开发效率和组件的复用性。

不要在循环、条件语句(如 if)、嵌套函数或 try/catch 代码块中调用 Hook。必须确保每次渲染时 Hook 的调用顺序一致。
只能在 React 函数组件或自定义 Hook 的主体顶层调用,不能在常规的 JavaScript 函数或类组件中调用。

useState 在函数组件中添加和管理局部状态。它返回一个状态变量和一个更新该状态的函数
useEffect 在函数组件中执行副作用操作,如数据获取、订阅事件、手动更改 DOM 或设置定时器等。它接受一个函数和一个可选的依赖项数组作为参数
useMemo 用于缓存计算结果。当依赖项不变时,返回缓存的值,从而避免每次渲染都进行昂贵的重复计算
useCallback 用于缓存回调函数的引用。当依赖项没有变化时,它会返回缓存的函数,避免子组件不必要的重新渲染
useRef 用于在函数组件中创建并返回一个可变的 ref 对象,常用于访问 DOM 元素或在多次渲染之间保持可变值
useContext 在函数组件中访问和消费 React Context 的数据,避免组件逐层传递 props
useReducer 类似Redux 的 reducer 函数,适合用于管理包含多个子值或复杂逻辑的本地状态
useOptimistic useOptimistic允许在进行异步操作(如网络请求)时乐观地更新用户界面,提升应用响应速度的体验。

3.1.useState

useState定义状态后,状态变化则函数组件会重新执行

初始值还可通过函数返回值来设置:const [state, setState] = useState(()=>{初始值}) 赋值前可以使用函数执行其他逻辑

setState中给的set函数是异步修改状态的,所以执行set函数后立马拿的state还是更新前的值

要拿状态更新后的最新值,要使用

useUffect(()=>{

        console.log(state)

},依赖项变化时触发的回调函数,[state])

如果在set修改状态时,连续累计修改会有更新不及时的bug

setCount(count+1)

setCount(count+1)

实际并没加2,因为set函数是同步执行,但是set内部是异步的,第二次执行set函数时,第一次的set结果还没有执行完成,需要改成setcount(新值)

或setCount((prev)=>prev+1) // 如果新值基于旧值计算得到,需要通过函数形参拿到旧值,return 出新值

如果要更改对象类型的值,并触发组件的重新渲染,必须用展开运算符或Object.assign()来生成一个新对象,使用新对象覆盖旧对象才能触发组件的重新渲染(内部判断对象是否变化,只判断了引用地址)

user.name= 'new' // 不生效

// 用新对象的引用替换旧对象的引用才会触发重新渲染

setUser(...user)或setUser(Object.assign({},user))

使用useState来模拟强制刷新

const [, forceUpdate] = useState({})

const onRefresh = ()=>{forceUpdate({})}

useRef

const inputRef = useRef<HTMLInputElement>(null) // 元素的初始值都是null

<input type="text" ref={inputRef}

inputRef.current.focus()

使用useRef还可以存储组件渲染周期的共享数据,或者是set函数变更前的数据

组件重新渲染rerender时,useRef不会重复初始化

ref.current变化时,不会导致组件重新渲染

ref.current不可以当做其他hooks的依赖项

在父组件中无法使用ref来直接引用函数式子组件,因为默认情况下组件不会暴漏内部DOM节点的ref

const childRef = useRef(null)

<Child ref = {childRef} /> 会报错

需要使用React.forwardRef把函数式组件包装起来(他不是hooks,而是react提供的函数)

const Child = React.forward((props, ref)=>{

})

4.Redux和Mobx

MobX 和 Redux 是 React 生态中最主流的两个状态管理库。

Redux 遵循函数式编程,强调严谨和可预测性;而 MobX 采用响应式编程(面向对象),追求简洁和高效。

Redux 适用场景

  • 大型复杂项目:需要严格的单向数据流和强约束性,保证多人协作下的代码结构清晰。
  • 需要时间旅行调试(Time-traveling):Redux 的不可变状态和纯函数机制天然支持状态回溯、撤销/重做(如画板应用、复杂表格应用)。
  • 团队熟悉函数式编程:如果团队对纯函数、不可变数据有深入理解,能充分发挥 Redux 的优势。

MobX 适用场景

  • 中小型项目/快速迭代:上手简单,样板代码少,开发效率高。
  • 团队熟悉面向对象编程(OOP):MobX 的 Class + 装饰器/响应式 API 写法更符合大多数开发者的直觉。
  • 追求极致渲染性能:MobX 的自动依赖追踪机制能实现组件的精确更新,避免不必要的重渲染。

注:两者并非绝对互斥,也可以在项目中用 Redux 做全局状态管理,用 MobX 做组件局部的复杂状态管理器。

Redux

Redux 的核心概念包括:Store(单一数据源)、Action(描述动作的对象)、Reducer(处理状态变更的纯函数)。

核心特点:状态是不可变(Immutable)的,必须通过 dispatch(action) 触发更新,且 Reducer 必须是纯函数。

import { createSlice, configureStore } from '@reduxjs/toolkit';

// 1. 定义 Slice (包含 state 和 reducer)
const counterSlice = createSlice({
  name: 'counter',
  initialState: { value: 0 },
  reducers: {
    increment: (state) => {
      // RTK 内部使用 Immer,允许写“可变”逻辑,但底层仍生成不可变状态
      state.value += 1; 
    },
  },
});

// 2. 配置 Store
export const store = configureStore({
  reducer: { counter: counterSlice.reducer },
});

// 3. 在 React 组件中使用
// 读取状态: const value = useSelector(state => state.counter.value);
// 触发更新: useDispatch()(counterSlice.actions.increment());

MobX

MobX 的核心概念包括:Observable(可观察状态)、Action(修改状态的动作)、Computed(派生状态)、Observer(响应式组件)。

核心特点:状态是可变(Mutable)的,采用响应式编程自动追踪依赖,无需手动 dispatch。

import { makeAutoObservable } from 'mobx';
import { observer } from 'mobx-react-lite';

// 1. 定义 Store (面向对象风格)
class CounterStore {
  count = 0;
  constructor() {
    // 自动将属性标记为 observable,方法标记为 action,getter 标记为 computed
    makeAutoObservable(this); 
  }
  
  increment() {
    this.count += 1; // 直接修改状态,自动触发视图更新
  }
  
  get doubleCount() {
    return this.count * 2; // 自动缓存的派生状态
  }
}

const counterStore = new CounterStore();

// 2. 在 React 组件中使用
const Counter = observer(() => {
  return (
    <div>
      <p>{counterStore.count} - {counterStore.doubleCount}</p>
      <button onClick={() => counterStore.increment()}>+1</button>
    </div>
  );
});

1. 核心设计哲学对比

  • Redux:基于推模型(Push)和函数式编程。状态只读,必须通过纯函数(Reducer)返回新状态。强调过程明确,每一步变更清晰可查。

  • MobX:基于拉模型(Pull)+ 响应式和面向对象编程。状态可变,通过 Proxy/getter/setter 自动感知依赖并更新。强调结果响应,开发体验流畅。

2. 状态更新机制的区别

  • Redux:通过 dispatch 广播 Action,所有的 Reducer 都会被调用。更新粒度较粗,需要通过对比前后的 state(浅比较)来控制组件是否重渲染。

  • MobX:利用 observable 实现精确更新。当状态变化时,MobX 自动追踪哪些组件依赖了该状态,只通知依赖的组件更新,无关组件不受影响。

3. 异步处理与副作用

  • Redux:原生 Reducer 必须是纯函数,不能包含异步操作。必须借助中间件(如 Redux-Thunk、Redux-Saga)来处理异步逻辑,学习曲线较陡。

  • MobX:没有中间件概念。在 action 中可以直接使用 async/await 语法处理异步任务,代码更加简洁直观。

4. 调试与可预测性

  • Redux:可预测性极强。配合 Redux DevTools,可以轻松实现时间旅行调试、查看 Action 日志和状态快照,非常适合排查复杂 Bug。

  • MobX:由于状态修改路径较隐式(自动响应),调试相对困难,状态难以回溯。

5. MobX 底层原理

  • 面试官可能会问 MobX 的响应式原理。核心在于:MobX 将数据包装为 Observable,当组件(Observer)渲染时,MobX 会通过 reaction.track 拦截属性的 getter,自动收集依赖;当属性被修改(setter)时,自动通知收集到的依赖进行更新。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐