前端面试高频精讲(三)React 篇

本文详细介绍了React中的受控与非受控组件,生命周期函数的各个阶段,以及高阶组件的概念。此外,还探讨了Hooks的引入原因和React事件系统,特别是合成事件的特点。ReactFiber的引入改善了渲染性能,文章也讨论了导致React重新渲染的因素。最后,提到了Fragment和Portals等高级特性,以及如何在类组件中绑定this。
摘要由CSDN通过智能技术生成
  • 受控组件和非受控组件

  • 受控组件:可以通过 value 来进行双向数据绑定,例如 input 、textarea 等
  • 非受控组件:不能进行双向数据绑定,例如 div 、span 等
  • React 生命周期函数

  • 挂载:construct、render、componentDidMount
  • 渲染:render、componentDidUpdate
  • 卸载:componentWillUnMount
  • 什么是高阶组件

一个组件作为参数传入另一个组件中,返回一个新的组件,这个新的组件拥有这两个组件的功能和优点。例如 withRoute

  • 为什么会出现 hooks

  • 类组件代码量大,每次渲染都要实例化,占用内存,难以维护。项目中大量使用类组件容易造成内存泄漏和性能消耗问题。
  • 类组件通常是单例模式,复用性不高,也很难进行单元测试,难以测试。且类组件的状态管理很复杂,难以调试,容易导致错误和性能问题。
  • 类组件的数据和函数距离过远,不利于逻辑并和,对标 VUE2 和 VUE3 关系
  •  React 事件和普通 HTML 事件不同

  • React 是合成事件,做一个兼容性处理,能够性能优化。
  • 原生使用 addEventListener 监听的,React 使用 onChange 监听。
  • React 必须使用特定的 API 来更新组件状态。例如,使用 setState 方法更新组件状态时,必须使用 componentDidUpdate 作为回调函数。
  • 考虑组件的状态和 props,以确保正确的行为和数据绑定。例如,如果一个事件处理程序修改了组件的状态,那么它必须通过 useEffect 钩子来确保状态更新被正确地反映在组件上。
  • React 事件处理程序必须考虑异步操作和副作用。例如,如果一个事件处理程序执行了一个异步操作并返回一个 Promise,那么它必须使用 useEffect 钩子来确保该 Promise 在组件卸载时被正确地处理。
  • 什么是合成事件

合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象,其优点如下:

  • 兼容所有浏览器,更好的跨平台;
  • 将事件统一存放在一个数组,避免频繁的新增与删除 (垃圾回收)
  • 方便 react 统一管理和事务机制
  • React 高阶组件、renderprops、hooks的区别

  • 高阶组件 HOC、renderprops 和 hooks 都是用来扩展 React 组件功能的工具。
  • 高阶组件接收一个组件作为参数,并返回一个新的组件。常用于实现权限控制、路由跳转等功能。
  • renderprops 是将 props 作为函数的参数传递给组件,在组件内部调用 props 来动态渲染子元素。
  • hooks 是 16.8 新增的一个 API。renderprops、hooks 常用于实现动态渲染、数据绑定等功能,且只适用于函数式组件
  • React Fiber

  • React Fiber 是一种轻量级的、可变的数据结构,每个 Fiber 对象都有一个唯一的 ID和一些状态信息,如优先级、挂起时间等。
  • Fiber 的主要作用是将 React 的渲染任务划分为更小、更细粒度的部分,从而提高渲染效率,更好地管理内存和资源
  • Fiber 能够并行执行多个渲染任务,充分利用多核处理器的优势
  • Fiber 的引入对 React 的性能提升非常明显。使用了 Fiber 的 React 可以更好地处理大量的渲染任务,并在不同的组件之间高效地切换,还能减少阻塞和卡顿的情况。同时,Fiber 还可以帮助开发者更好地管理内存和资源,从而避免了一些常见的性能问题。
  • 哪些方法会让 React 重新渲染

  • 组件的状态发生变化,例如 props、state、context、refs等
  • 类组件的 this.setState 或者函数组件 useState 中的 setList
  • 组件的父组件或者祖先组件的状态或属性发生了变化,导致子组件需要重新渲染
  • 组件卸载的时候调用 componentWillUnMount 也会重新渲染
  • 组件的 shouldComponentUpdate 方法返回值为 true 时也会重新渲染
  • 组件的 key 属性发生了变化,导致 React 需要重新计算子树结构并进行重新渲染。
  • React 的 render 函数做了什么

  • render 函数是组件渲染的核心方法,它的作用是将组件的状态和属性转化为虚拟 DOM 转换成 HTML 元素,并将其渲染到页面上。具体来说,render 函数做了以下几件事情:
  • 获取组件的 props 和 state
  • 根据 props 和 state 的值,进行一些必要的处理,例如计算属性、修改状态等。
  • 根据组件的结构和样式,生成一个 UI 。
  • 需要的话,可以通过 render 向页面添加事件监听器,便于用户交互或其他事件发生时执行相应的操作。
  • React 如何判断什么时候重新渲染组件

  • 手动写一个 shouldComponentUpdate
  • useEffect
  • 使用 pure.component
  • 声明组件的几种方式

  • function
  • class 类名 extends React.component
  • 箭头函数
  • 高阶组件
  • ES5 中的 React.createClass 来创建类组件
  • 有状态组件和无状态组件

  • 16.8之前,函数组件被称为无状态组件,因为它无法实现响应式数据,没有生命周期等,16.8之后,函数组件有了 hooks,可以实现响应式数据
  • 类组件也叫有状态组件,因为它可以实现响应式数据,有生命周期

有状态组件使用场景:

  • 需要在组件内部保存一些数据的场景,例如表单组件、评论组件等;
  • 需要在组件内部处理一些复杂的逻辑的场景,例如图表组件、表格组件等;
  • 需要在多个子组件之间共享数据的场景,例如路由组件、应用程序入口组件等。

无状态组件使用场景:

  • 只要求展示数据的场景,例如图标、按钮、标签等;
  • 需要在多个组件之间共享数据的场景,例如导航栏、页脚等;
  • 需要复用相同结构的组件的场景,例如列表、表格等。
  • Fragment 的理解

Fragment 是 React 中一种特殊的组件,将多个子组件组合成一个单独的节点,可以避免重复渲染和不必要的性能开销。对标 Vue2 中的 templete

  • Portals 的理解

  • Portals 通过创建一个“传送门”来传送 UI。具体来说,Portals 允许将子组件的内容“传送”到父组件中,并且可以实现父子组件之间的通信。对标 Vue3 中的 teleport
  • 说下你都是用过哪些React Hooks ?

1、React 自带的 hooks:

  • useState:设置响应式数据。
  • useEffect:副作用钩子,用于订阅事件、发送网络请求等。它是异步的会执行多次,执行时机是渲染之后,所以容易出现页面闪动现象
  • useLayoutEffect:同步的只会进行一次渲染,执行时机是渲染之前,常用于解决页面闪动问题,可以性能优化
  • useContext:访问上下文,共享数据。
  • useReducer:管理复杂的状态逻辑。
  • useRef:获取DOM元素。
  • useMemo:计算属性。
  • useId:返回一个id。
  • useCallback:用于缓存一个回调函数。
  • useTransition:异步渲染页面,可以性能优化

2、插件带的 hooks:

  • useLocation:获取路由的路径、参数等信息
  • useHistory:获取路由导航相关方法,如“push”、“replace”等
  • useNavigate:用于路由跳转。
  • useParams:获取组件的参数
  • Portals:相当于 vue3 的传送门
  • useDispatch:获取 dispatch 函数,用于触发 Redux 的动作
  • useSelector:从 Redux store 中选择并访问状态数据。
  • useAppSelector:负责将数据绑定全局数据。
  • useAppDispatch:将数据传给全局处理函数,他调用会返回一个 dispatch 函数,这个函数可以调用 reducer 函数。

3、自定义 hooks:

  • useMousePosition(获取鼠标移动的坐标)
  • usePagination(用于分页)
  • useLocalStorage(本地存储)
  • 类组件中绑定 this 的方式有哪些?

  • 使用 bind
  • 使用箭头函数,它的 this 指向上下文
  • 在构造函数中,使用 bind
class A extends React.Component{
    construct(props){
        super(props)
        this.state={
            num:11
        }
    }
    this.addnum = this.addnum.bind(this)
}


addnum =()=>{
    this.state.num+1
}
  • 说下对 Redux 的理解

  • Redux 是一个强大的状态管理工具,它能更好地组织和管理应用程序的状态。
  • React Component 需要获取一些数据, 然后它就告知 Store 需要获取数据,Store 接收到之后去 Reducer 查一下,Reducer 会告诉 Store 应该给这个组件什么数据
  • 说下对 MobX 的理解

看主页 MobX 的使用讲解
  • 说下对 RTK 的理解

看主页 RTK 的使用讲解

  • Redux、MobX 、ReduxToolkit 区别

它们都是状态管理库,下面是它们之间的一些区别:

  • Redux 和 ReduxToolkit 的 API 设计比较相似,都是基于 ES6 的类和方法来实现的。而 MobX 则采用了更简单的函数式 API,使得开发者可以更加方便地使用。
  • ReduxToolkit 在性能方面进行了一些优化,例如支持异步操作、自动生成 connect 函数等,从而可以提高应用程序的性能和响应速度。而 Redux 和 MobX 在性能方面的表现相对较为平均。
  • ReduxToolkit 在功能扩展方面比 Redux 和 MobX 更丰富,例如支持多个 Store、提供高阶组件等。而 Redux 和 MobX 则相对简单,只提供了基本的功能。
  • setState 是同步还是异步的,调用后做了什么?如何实现同步?

  • setState 是异步的。当调用 setState() 方法时,React 会将更新后的 state 放入一个队列中,并在下一次渲染时执行,这里注意它不会立即执行,需要立即执行某些操作的话,使用 componentDidUpdate()方法。
  • 实现同步:使用一个回调函数,这个回调函数是更新完后执行
this.setState({
    num:12
},()=>{
    console.log(num)
})
  • Vue 和 React 的区别

  • Vue 是一个渐进式的框架,React 是一个轻量级的库。
  • Vue 采用的是组件式开发,将 HTML+JS+CSS 写在一起,React 使用的是 JSX 的语法。
  • Vue 采用 MVVM 框架,React 是单向数据流。
  • Vue 不兼容 IE8 ,React 兼容 IE8。
  • Vue 开发速度快,代码量小,自带全家桶不够灵活,React 第三方生态繁荣,较为灵活但是代码量大。
  • React 中常见的组件通信方式

  • 父子组件传值:父组件准备一个 state 数据,子组件使用 props / this.props 接收 
  • 子父组件传值:父组件准备一个回调函数,子组件使用 props / this.props 接收回调函数传参,父组件接收参数
  • 兄弟组件传值:使用一个父组件作为中间件通信,父组件准备一个回调函数,哥组件使用 props / this.props 接收回调函数传参给父组件,弟组件又通过 props / this.props 接收父组件中的数据
  • 跨组件传值:使用 provider 和 comsumer
  • 可以使用状态管理工具,例如 Redux、MobX 等
  • 钩子函数 useContext 共享数据
  • 使用 localStorage 等存储方式
  • router 路由也可以进行一些传值
  • useEffect 和 useLayoutEffect 的区别

  • useEffect :它会在组件渲染后执行,异步的。
  • useLayoutEffect:它会在组件渲染前执行,最终真实的DOM只渲染一次,同步的。
  • 用 TS 结合 React 项目说下使用场景

  • 函数组件 FC:可以判断很多 JSX 语法错误
  • 函数组件 props 传值限制
  • RTK 的 TS 限制类型
  • axios 封装时,接口设计
  • React 的设计思路和理念

  • 组件化开发:React 将整个应用程序看作是由多个组件组成的,每个组件都有自己的状态和行为。这种组件化的开发方式使得代码更加模块化、可重用、易于维护和扩展。
  • 虚拟 DOM:React 通过使用虚拟 DOM 来提高渲染性能。
  • JSX 语法:React 使用 JSX 来描述 UI 元素。
  • 单向数据流:React 采用单向数据流的设计思想,即从父组件到子组件的数据传递只能是单向的。这种设计方式使得应用程序的状态管理更加简单、清晰和可控。
  • React 如何实现 v-show

  • 组件上使用的是父子组件传值,父组件传递一个 ‘v-show’ ,子组件使用 props 接收 ‘v-show’,内部传递一个 boolean 值,来控制 display 的属性是 none 还是 block 
  • 元素上直接使用 style 属性
  • React 的遍历方法

  • 常使用 map、forEach
  • 为什么 useState 使用数组而不是对象

  • 数组是可变的,可以在运行时修改其内容,而对象则不是。如果将状态设置为对象,当状态发生变化时,需要重新渲染整个组件,这会影响性能。
  • 数组可以通过索引来访问其元素,这样可以方便地获取或修改数组中的特定元素。而对象则需要通过键来访问其元素,这会增加代码的复杂度。
  • 在早期版本的 React 中,只有数组支持浅拷贝,这意味着当我们将状态从父组件传递给子组件时,只有数组会被浅拷贝到子组件的状态中。而对象浅拷贝会导致状态不同步的问题。
  • React-Router 中的 Link 和 a 标签的区别

  • Link 可以实现传参,它通过 to 来跳转到对应路径,a 通过 href 来跳转不能传值
  • Link 跳转不会进行页面刷新,a 会有默认刷新效果
  • Link 可以实现重定向、历史记录等,a 标签只能用于普通的跳转
  • Link 可以说是 a 标签的一个封装,主要做了一下三步:1、定义 onClick 方法,执行该 onClick 方法;2、点击时阻止 a 标签默认行为;3、再取得跳转 href ,此时只是链接变了,并没有刷新页面
  • 如何解决 props 嵌套过深的问题

使用其他传值方式,例如 Redux、MobX 等或者使用 useContext 钩子函数

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值