React 常见的知识点

基础概念类

1. 什么是 React?

React 是一个用于构建用户界面的 JavaScript 库,由 Facebook 开发并开源。它采用组件化的思想,允许开发者将复杂的 UI 拆分成多个小的、可复用的组件,通过组合这些组件来构建整个应用程序。React 使用虚拟 DOM(Virtual DOM)来提高渲染效率,通过比较新旧虚拟 DOM 的差异,只更新需要更新的真实 DOM 节点。

2. 什么是 JSX?它有什么作用?

JSX 是 JavaScript XML 的缩写,它是一种 JavaScript 的语法扩展,允许在 JavaScript 代码中编写类似 XML 的标记。JSX 的作用主要有:

  • 更直观的 UI 描述:使代码更接近 HTML 结构,方便开发者编写和理解 UI 界面。
  • 静态检查:可以在编译时进行静态检查,提前发现一些错误。
  • 与 JavaScript 无缝集成:可以在 JSX 中嵌入 JavaScript 表达式,实现动态内容的展示。

示例:

const element = <h1>Hello, {name}!</h1>;

3. 什么是虚拟 DOM(Virtual DOM)?为什么要使用它?

虚拟 DOM 是一种轻量级的 JavaScript 对象,它是真实 DOM 的抽象表示。虚拟 DOM 是一个树形结构,每个节点对应一个真实的 DOM 元素。

使用虚拟 DOM 的原因:

  • 提高性能:在更新 UI 时,直接操作真实 DOM 的代价较高。React 会先在虚拟 DOM 上进行修改,然后通过比较新旧虚拟 DOM 的差异,只更新需要更新的真实 DOM 节点,减少了真实 DOM 的操作次数,从而提高了性能。
  • 跨平台:虚拟 DOM 是一个抽象的概念,不依赖于具体的平台,可以方便地实现跨平台开发,如 React Native 就是基于虚拟 DOM 实现的。

组件相关类

1. React 组件有哪几种类型?它们有什么区别?

React 组件主要分为两类:函数组件和类组件。

  • 函数组件:是一个纯函数,接收 props 作为参数,并返回一个 React 元素。函数组件没有自己的状态和生命周期方法,也被称为无状态组件。
    示例:
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
  • 类组件:是一个继承自 React.Component 的类,它有自己的状态和生命周期方法。类组件可以使用 this.state 来管理组件的状态,通过 this.props 接收外部传递的属性。
    示例:
class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

区别:

  • 状态管理:函数组件没有自己的状态,只能通过 props 接收外部数据;类组件可以使用 this.state 管理组件的状态。
  • 生命周期方法:函数组件没有生命周期方法;类组件有一系列的生命周期方法,如 componentDidMountcomponentDidUpdate 等。
  • 代码复杂度:函数组件代码更简洁,适合简单的展示性组件;类组件代码相对复杂,适合处理复杂的逻辑和状态管理。

2. 什么是 propsstate?它们有什么区别?

  • props:是 properties 的缩写,用于在组件之间传递数据。props 是只读的,组件不能修改自己的 props,只能通过父组件重新传递新的 props 来更新数据。
  • state:是组件内部的状态,用于管理组件自身的数据。state 是可变的,组件可以通过 this.setState 方法来更新 state,从而触发组件的重新渲染。

区别:

  • 数据来源props 是从父组件传递过来的;state 是组件内部自己管理的数据。
  • 可变性props 是只读的;state 是可变的。
  • 使用场景props 用于在组件之间传递数据;state 用于管理组件内部的动态数据。

3. 如何在 React 中实现组件间通信?

  • 父组件向子组件通信:通过 props 传递数据。父组件将数据作为属性传递给子组件,子组件通过 props 接收数据。
    示例:
// 父组件
function Parent() {
  const message = "Hello from parent";
  return <Child message={message} />;
}

// 子组件
function Child(props) {
  return <p>{props.message}</p>;
}
  • 子组件向父组件通信:通过回调函数。父组件将一个回调函数作为 props 传递给子组件,子组件在需要时调用该回调函数并传递数据给父组件。
    示例:
// 父组件
function Parent() {
  const handleChildData = (data) => {
    console.log(data);
  };
  return <Child onData={handleChildData} />;
}

// 子组件
function Child(props) {
  const sendData = () => {
    props.onData("Hello from child");
  };
  return <button onClick={sendData}>Send Data</button>;
}
  • 非父子组件通信:可以使用事件总线(Event Bus)、Context API 或状态管理库(如 Redux、MobX)来实现。

生命周期与 Hooks 类

1. 简述 React 类组件的生命周期方法。

React 类组件的生命周期方法可以分为三个阶段:挂载阶段、更新阶段和卸载阶段。

  • 挂载阶段:组件被创建并插入到 DOM 中。
    • constructor:组件的构造函数,用于初始化 state 和绑定事件处理函数。
    • static getDerivedStateFromProps:在组件挂载和更新时都会调用,用于根据 props 更新 state
    • render:渲染组件的 UI。
    • componentDidMount:组件挂载完成后调用,常用于发起网络请求、订阅事件等。
  • 更新阶段:组件的 propsstate 发生变化时,组件会重新渲染。
    • static getDerivedStateFromProps:同上。
    • shouldComponentUpdate:用于决定组件是否需要重新渲染,返回 true 表示需要重新渲染,返回 false 表示不需要。
    • render:同上。
    • getSnapshotBeforeUpdate:在 DOM 更新之前调用,用于获取 DOM 更新前的一些信息。
    • componentDidUpdate:组件更新完成后调用,常用于更新 DOM 或发起网络请求。
  • 卸载阶段:组件从 DOM 中移除。
    • componentWillUnmount:组件卸载前调用,常用于清理定时器、取消订阅等操作。

2. 什么是 React Hooks?常见的 Hooks 有哪些?

React Hooks 是 React 16.8 引入的新特性,它允许在不编写 class 的情况下使用 state 和其他 React 特性。Hooks 可以让你在不改变组件结构的情况下复用状态逻辑,使代码更加简洁和可维护。

常见的 Hooks 有:

  • useState:用于在函数组件中添加 state
    示例:
import React, { useState } from 'react';

function Example() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}
  • useEffect:用于在函数组件中处理副作用,如数据获取、订阅、定时器等。
    示例:
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
    return () => {
      // 清理副作用
    };
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}
  • useContext:用于在函数组件中使用 Context API。
  • useReducer:是 useState 的替代方案,用于处理复杂的状态逻辑。
  • useCallback:用于缓存函数,避免在每次渲染时都重新创建函数。
  • useMemo:用于缓存计算结果,避免在每次渲染时都进行复杂的计算。

3. useStateuseReducer 有什么区别?

  • 使用场景
    • useState 适用于简单的状态管理,状态的更新逻辑比较简单,通常只涉及到对状态的简单修改。
    • useReducer 适用于复杂的状态管理,状态的更新逻辑比较复杂,涉及到多个状态的组合或复杂的计算。
  • 语法
    • useState 使用一个初始值来初始化状态,并返回一个数组,数组的第一个元素是当前状态,第二个元素是更新状态的函数。
    • useReducer 使用一个 reducer 函数和一个初始状态来初始化状态,并返回一个数组,数组的第一个元素是当前状态,第二个元素是触发状态更新的 dispatch 函数。

示例:

// useState
import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

// useReducer
import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
    </div>
  );
}

性能优化类

1. 如何优化 React 应用的性能?

  • 使用 shouldComponentUpdateReact.memoshouldComponentUpdate 是类组件的生命周期方法,用于决定组件是否需要重新渲染;React.memo 是函数组件的高阶组件,用于浅比较 props,如果 props 没有变化,则不会重新渲染组件。
  • 使用 React.lazySuspenseReact.lazy 用于动态导入组件,Suspense 用于在组件加载时显示加载提示,实现代码分割,减少首屏加载时间。
    示例:
const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  return (
    <div>
      <React.Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </React.Suspense>
    </div>
  );
}
  • 避免不必要的渲染:尽量减少 stateprops 的变化,避免在 render 方法中进行复杂的计算。
  • 使用事件委托:将事件处理函数绑定到父组件上,通过事件冒泡来处理子组件的事件,减少事件处理函数的数量。
  • 优化 CSS:避免使用内联样式,使用 CSS 类名来管理样式,减少重排和重绘。

2. 什么是 React.memo?它和 shouldComponentUpdate 有什么区别?

  • React.memo:是一个高阶组件,用于函数组件的性能优化。它会对组件的 props 进行浅比较,如果 props 没有变化,则不会重新渲染组件。
    示例:
const MyComponent = React.memo((props) => {
  return <div>{props.message}</div>;
});
  • 区别
    • 适用组件类型React.memo 适用于函数组件;shouldComponentUpdate 适用于类组件。
    • 比较方式React.memo 进行浅比较;shouldComponentUpdate 可以自定义比较逻辑,进行更复杂的比较。

其他类

1. 什么是 React Router?如何使用它实现路由功能?

React Router 是 React 官方推荐的路由库,用于实现单页面应用(SPA)的路由功能。它提供了不同的路由组件,如 BrowserRouterHashRouterRouteLink 等。

使用步骤:

  1. 安装 React Router:npm install react-router-dom
  2. 引入必要的组件:
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
  1. 创建路由配置:
function App() {
  return (
    <Router>
      <nav>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/about">About</Link></li>
        </ul>
      </nav>
      <Route path="/" exact component={Home} />
      <Route path="/about" component={About} />
    </Router>
  );
}

function Home() {
  return <h1>Home Page</h1>;
}

function About() {
  return <h1>About Page</h1>;
}

2. 什么是 Context API?它有什么作用?

Context API 是 React 提供的一种在组件树中共享数据的方式,避免了通过 props 层层传递数据的繁琐。它主要用于在多个组件之间共享一些全局数据,如用户信息、主题颜色等。

使用步骤:

  1. 创建 Context:
const MyContext = React.createContext();
  1. 提供数据:
<MyContext.Provider value={/* 要共享的数据 */}>
  {/* 子组件 */}
</MyContext.Provider>
  1. 消费数据:
// 类组件
class MyComponent extends React.Component {
  static contextType = MyContext;
  render() {
    const value = this.context;
    return <div>{value}</div>;
  }
}

// 函数组件
function MyComponent() {
  const value = useContext(MyContext);
  return <div>{value}</div>;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,490评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,581评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,830评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,957评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,974评论 6 393
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,754评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,464评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,357评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,847评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,995评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,137评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,819评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,482评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,023评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,149评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,409评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,086评论 2 355