React整理

讲概念,说用途,理思路,列优缺点

1. 什么是 React?

(历史): react是一个ui框架,jquery不是框架,只是一个工具库,随着pc性能提高,页面效果也需要提升,但是jquery没有一个模式,没发组织代码, angularjs 之后推出,提出了双向绑定的概念,是angularjs的最大特点。 View = fn(props)

(答案) react 通过组件化的方式,解决工程化和视图层的开发复用问题

声明式:直观和组合 组件化,降低系统间的耦合性,提高功能内部的聚合性 通用性: 虚拟dom不局限于web开发

react 不是一揽子框架,在技术选型上有比较高的成本

2. 为什么要用jsx

(为什么要用?这类问题) 一句话解释 核心概念 方案对比

关注点分离

jsx是js的语法扩展,react中不强制使用jsx, jsx是createElement的一个语法糖 模版不应该是开发中的关注点,违反 关注点分离 原则。所以没有引入模版语法。

3. 类组件和函数组件有什么区别

4. setState 是同步更新还是异步更新

合成事件,react 给dom容器中监听事件,进行事件委托。 捕获到事件之后,模拟冒泡捕获,传递给对应的组件。 setState 不是真的异步,只是看起来像异步。 在react可以控制的事件中 ,isBatchingUpdates为ture,则为异步更新 在原生事件中,为false

异步的情况: 保持内部的一致性, 后续架构更新

6. 为什么使用 react hook

why what how

函数式组件更契合react 的理念

类组件 this 的数据是可以被修改的,一些情况(setTimeout)下会打破了数据和渲染动作之间的关联 hook补齐了相较于类组件缺失的东西

hook 两个经典 useState,useEffect

useEffect弥补了生命周期的缺陷,能够为函数式组件引入副作用操作

why 告别难以理解的class,class 的 this 难以理解 生命周期的不合理,逻辑一度与生命周期耦合在一起。 可以通过自定义hook 达到不破坏组件结构,又能够实现逻辑复用的效果。

hooks 暂时还不能完全补齐类组件的能力 hooks在使用规则层面有严格的约束

7. hooks的原理

how

hooks 的本质是链表

mountState 首次渲染时,构建链表并渲染 updateState 按顺序调用之前构建好的链表,取出对应的数据信息进行渲染

hooks 只在函数中调用 不能再循环或者条件中调用 以上两点是为了保证 hooks 的执行顺序 为什么顺序这么重要

8. 为什么需要虚拟dom

虚拟dom的价值不在性能

在 React 中,虚拟 DOM 是一个轻量级的 JavaScript 对象树,它以组件树的形式描述整个用户界面。每个虚拟 DOM 节点都与实际 DOM 中的节点对应,并包含有关节点的信息。

虚拟 DOM 的作用是提供一种方式来更新和渲染界面。当组件的状态发生变化时,React 会生成一个新的虚拟 DOM 树,然后通过比较前后两个虚拟 DOM 树的差异,确定实际需要更新的部分。

通过diff 和 patch 可以最小化实际 DOM 操作的次数。React 会找出需要添加、更新或删除的 DOM 节点,然后进行一次批量更新,以最小化对实际 DOM 的访问和操作。

通过使用虚拟 DOM,React 实现了高效的 UI 更新和渲染。它只更新发生变化的部分,而不是整个界面,从而提高性能和响应性。

虚拟dom 解决的关键问题: 提高研发体验和研发效率 可以跨平台 批量更新时可以缓冲每次更新

9. react 的 栈调和

通过 ReactDOM 等类库让虚拟dom 与真实的dom 同步,这一过程叫做协调。

10. diff算法的原理

想要找出两个树之间的结构差异 如果要一个一个遍历,时间复杂度将达到n3 diff 算法性能突破的关键点在于分层对比,类型一致的节点才继续diff,同一层节点设置key属性

11. fiber 调和

fiber 可中断,可恢复,优先级

每一个更新任务都会被赋予一个优先级 高优先级的任务可以插队低优先级的任务

6. React 中的生命周期方法有哪些?请描述它们的用途和调用顺序。

React 组件的生命周期方法是一组在组件不同阶段被调用的函数,用于在特定时机执行一些操作。以下是 React 类组件中常用的生命周期方法:

  • constructor(props):组件的构造函数,在组件实例化时调用。通常用于初始化组件的状态和绑定事件处理函数。

  • static getDerivedStateFromProps(props, state):在组件实例化、接收新属性(props)时被调用。它接收新的属性和当前状态,并返回一个新的状态对象。

  • render():必须的生命周期方法,在组件实例化、更新时都会被调用。它负责根据组件的状态和属性返回要渲染的 React 元素。

  • componentDidMount():在组件首次渲染完成后调用。通常用于执行异步操作、订阅事件等初始化工作。

  • shouldComponentUpdate(nextProps, nextState):在组件更新前被调用,用于决定是否需要重新渲染组件。通过返回 true 或 false 来控制更新,默认返回 true。

  • getSnapshotBeforeUpdate(prevProps, prevState):在组件更新前被调用,在最终渲染前获取当前的 DOM 状态。常用于在组件更新前保存一些需要的信息。

  • componentDidUpdate(prevProps, prevState, snapshot):在组件更新后被调用,用于处理更新后的操作,比如更新 DOM、请求数据等。

  • componentWillUnmount():在组件卸载(销毁)前被调用。通常用于清理工作,比如取消订阅、清除定时器等。

生命周期方法的调用顺序如下:

  • 构造函数 (constructor)
  • 静态方法 (static getDerivedStateFromProps)
  • 渲染 (render)
  • 组件挂载完成 (componentDidMount)
  • 属性更新时的判断 (shouldComponentUpdate)
  • 属性更新 (render)
  • 更新完成 (componentDidUpdate)
  • 组件卸载 (componentWillUnmount)

需要注意的是,在 React 16.3 版本之后,一些生命周期方法被标记为过时(deprecated)或废弃(unsafe)。可以参考官方文档以获取更详细的信息。

8. React 中如何处理表单输入?

在 React 中处理表单输入需要注意两个方面:表单元素的状态管理和事件处理。

首先,为了实时跟踪表单元素的状态,可以使用 React 的状态管理机制(如 useState 或类组件中的状态)。将表单元素的值与状态进行绑定,这样当输入发生变化时,状态会更新。

其次,为了响应用户的输入,可以使用表单元素的事件处理函数,比如 onChange 事件。当用户输入发生变化时,事件处理函数会被触发,并将新的输入值传递给状态管理机制,以更新状态。

以下是一个示例,展示如何处理表单输入:

jsxCopy code

import React, { useState } from 'react'; function FormExample() { const [name, setName] = useState(''); const handleInputChange = (event) => { setName(event.target.value); }; const handleSubmit = (event) => { event.preventDefault(); // 处理表单提交逻辑 console.log('提交的姓名:', name); }; return ( <form onSubmit={handleSubmit}> <label> 姓名: <input type="text" value={name} onChange={handleInputChange} /> </label> <button type="submit">提交</button> </form> ); }

在上面的例子中,FormExample 组件通过 useState 来管理输入框的值 name。通过 onChange 事件监听输入框的变化,将新的值更新到状态中。在表单提交时,调用 handleSubmit 函数来处理表单提交的逻辑。

9. React 中的 keys 属性有什么作用?为什么在列表渲染中使用它是重要的?

keys 属性是用于帮助 React 跟踪和识别列表项的唯一标识。它在列表渲染中起着重要的作用。

在 React 中,当渲染列表时,每个列表项都需要具有一个唯一的 key 属性。这个 key 属性可以是一个字符串或数字,用于帮助 React 识别列表中的每个元素。

使用 key 属性的好处有:

  • 提高性能:key 属性帮助 React 识别哪些列表项发生了变化。在更新列表时,React 可以根据 key 属性判断哪些列表项需要重新渲染,而不是重新渲染整个列表。
  • 维持组件状态:如果列表项没有唯一的 key,当列表项发生变化时,React 可能会错误地重新创建组件实例,导致组件状态丢失。

以下是一个示例,展示如何在列表渲染中使用 keys 属性:

jsxCopy code

function ListExample() { const items = ['Item 1', 'Item 2', 'Item 3']; return ( <ul> {items.map((item, index) => ( <li key={index}>{item}</li> ))} </ul> ); }

在上面的例子中,使用 map 方法渲染 items 数组中的每个元素。通过给每个列表项设置 key={index},确保每个列表项都有一个唯一的标识。

10. React 中的组件通信有哪些方式?

在 React 中,组件之间进行通信可以通过以下几种方式:

  • 属性传递(Props):父组件可以通过属性将数据或回调函数传递给子组件。子组件通过 props 对象接收和使用这些属性。

  • 上下文(Context):上下文允许在组件树中共享数据,避免了通过层层传递属性的麻烦。可以使用 React.createContext 创建上下文对象,并通过 ProviderConsumer 组件在组件树中传递和使用上下文数据。

  • 全局状态管理(Redux、MobX):使用全局状态管理库,如 Redux 或 MobX,可以将应用程序的状态集中管理。这允许组件在不同层级之间共享和访问状态,并通过派发操作或观察状态的变化进行通信。

  • 发布/订阅模式(Event Emitter):通过使用事件发射器(Event Emitter)或事件总线,组件可以订阅和发布事件,实现解耦的通信机制。

这些方式各有优缺点,根据具体的场景选择合适的方式来实现组件之间的通信。