react面试题

本文详细解读React的核心特性,包括jsx语法、虚拟DOM、生命周期管理、状态更新机制、事件处理、组件间通信、受控与非受控组件、Fiber架构优化、Redux和中间件、内存泄漏及其预防。
摘要由CSDN通过智能技术生成

1. 说说你对react的理解?有哪些特性?

React是用于构建用户界面的javascript库,只提供了ui层面的解决方案。遵循组件设计模式,声明式编程范式和函数式编程概念,让前端应用程序变得更加高效灵活。使用虚拟dom来操作dom,遵循从高阶组件到低阶组件的单向数据流。将界面分成两个独立的小块,每个小块都是一个组件,这些组件可以进行组合,嵌套组合,嵌套并且构成了整体页面。react 类组件使用一个名为 render() 的方法或者函数组件return,接收输入的数据并返回需要展示的内容

特性:Jsx语法、单项数据绑定、 虚拟dom 、声明式编程 ,component

2. 说说Real DOM和Virtual DOM的区别?优缺点?

(1)虚拟dom不会进行重绘与回流。真实dom会进行重绘与回流。

(2)虚拟dom的总消耗=虚拟dom增删改+真实dom差异增删改+排版与重绘。真实dom的总消耗=真实dom完全增删改+排版与重绘。

真实 DOM 的优势:易用

缺点:效率低,解析速度慢,内存占用量过高,性能差:频繁操作真实 DOM,易于导致重绘与回流

使用虚拟 DOM 的优势如下:

简单方便:如果使用手动操作真实 DOM 来完成页面,繁琐又容易出错,在大规模应用下维护起来也很困难

性能方面:使用 Virtual DOM,能够有效避免真实 DOM 数频繁更新,减少多次引起重绘与回流,提高性能

跨平台:React 借助虚拟 DOM,带来了跨平台的能力,一套代码多端运行

缺点:

在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化

首次渲染大量 DOM 时,由于多了一层虚拟 DOM 的计算,速度比正常稍慢

3. 说说React生命周期有哪些不同的阶段?每个阶段对应的方法是?

挂载阶段:

constructor:组件被创建时调用,用于初始化组件的状态和绑定事件处理函数。

render:根据组件的props和state返回一个React元素,用于构建组件的UI。

ComponentDidMount:组件被插入到DOM树中后调用,用于进行异步操作、订阅事件等。

更新阶段:

static getDerivedStateFromProps:在接收到新的props时调用,用于根据props更新组件的状态。

shouldComponentUpdate:在组件更新前调用,用于决定是否重新渲染组件。 render:根据组件的props和state返回一个React元素,用于构建组件的UI。 getSnapshotBeforeUpdate:在组件更新前调用,用于获取更新前的DOM状态。 componentDidUpdate:组件更新后调用,用于进行DOM操作、网络请求等。

销毁阶段:componentWillUnmount:组件被从DOM树中移除前调用,用于清理定时器、取消订阅等。

4. 说说React中setState执行机制?

  1. 异步执行:setState 方法是异步执行的,即调用 setState 后,并不会立即更新组件的状态。React 会将新的状态合并到一个队列中,等到适当的时机才会批量更新组件的状态。

  2. 队列机制:当调用 setState 方法时,React 会将新的状态添加到更新队列中,并标记组件为“待更新”。如果在同一个事件循环中多次调用 setState,React 会将这些更新合并成一个更新。

  3. 批量更新:React 会在合适的时机(比如当前事件循环结束、定时器触发、异步请求完成等)对队列中的更新进行批量处理,即批量更新组件的状态。这样可以避免频繁的 DOM 操作,提高性能和效率。

  4. 合并更新:在进行批量更新时,React 会对更新队列进行合并,只进行一次 DOM 操作。React 会根据组件的更新策略(比如 shouldComponentUpdate)判断是否需要更新组件的状态,并重新渲染组件。

5. 说说react的事件机制?

React的事件机制是基于合成事件的。React通过在DOM节点上注册少量的全局事件监听器,来处理所有的事件。当事件触发时,React会使用单一的事件监听器来捕获并分发事件。React的合成事件是对原生浏览器事件的跨浏览器封装。它提供了与原生事件相似的属性和方法,并且具有跨浏览器的兼容性。在React中,通过在组件元素上定义特定的事件属性,可以将事件处理函数与特定的事件关联起来。当事件触发时,React将创建一个合成事件对象,并将其传递给事件处理函数。事件处理函数可以访问合成事件对象,以获取有关事件的信息。

6. React组件之间如何通信?

父传子:在父组件中的子组件上挂载一个自定义属性,子组件通过props来接收父组件传递过来的值 子传父:在在父组件中的子组件上挂载一个自定义方法,子组件也是通过props接收函数并调用在上面挂载传递的参数,父组件上定义的方法第一个参数就是接收到的值 Context:在文件夹创建一个createContext空对象,在父组件中通过provider标签来包裹数据,在子组件中通过customer标签来接收,接收一个回调函数

7. 说说你对受控组件和非受控组件的理解?应用场景?

受控组件:就是受控制的组件。受setstate的控制,受控组件就是表单的回调,提交用户信息,多用于修改操作。

非受控组件指的是,表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值。 在非受控组件中,可以使用一个ref来从DOM获得表单值。

8. 说说你对fiber架构的理解?解决了什么问题?

Fiber 架构是 React 在 16 版本中引入的一种新的协调机制,旨在解决 React 在处理大型应用中的性能问题和用户体验问题。

传统的 React 渲染过程是同步的,即一旦开始渲染,就会一直执行完整个渲染过程,期间无法中断。这种方式在处理大量计算密集型操作或者渲染大型组件树时,可能会导致主线程被长时间占用,造成页面卡顿,用户交互不流畅。

Fiber 架构的目标是将 React 的渲染过程分解为多个小任务,使得渲染过程可中断和恢复,以实现更好的用户体验。Fiber 架构的核心是虚拟的 Fiber 节点树,它以链表的形式表示组件树,通过优先级调度算法和协调器的配合,实现了任务的拆分、优先级调度和任务中断。

Fiber 架构解决了以下问题:

  1. 增量渲染:Fiber 架构将渲染过程拆分为多个小任务,每个任务可以在主线程空闲时执行,这样就可以实现增量渲染,将渲染过程分散到多个帧中,减少了单个渲染过程的时间,提升了用户体验。

  2. 任务优先级调度:Fiber 架构引入了任务优先级的概念,通过给不同任务赋予不同的优先级,可以根据任务的重要性和紧急程度来调度任务的执行顺序,保证用户交互的响应速度。

  3. 中断和恢复:由于 Fiber 架构的任务是可中断的,当有更高优先级的任务需要执行时,可以中断当前任务的执行,将控制权交还给浏览器,让用户交互能够得到及时响应。当浏览器空闲时,可以恢复中断的任务,继续执行。

  4. 错误边界:Fiber 架构引入了错误边界的概念,可以将错误隔离到组件树的更上层,避免整个应用崩溃。通过错误边界,可以优雅地处理组件内部的错误,提高应用的健壮性和可靠性。

9. 说说react diff的原理是什么?

  1. 双端比较:React会同时遍历新旧两棵树,逐个比较。

  2. 同层比较:React会逐层比较,如果当前层有变化,会继续比较下一层,如果当前层没有变化,则跳过该层的所有子级节点。

  3. 标识符提高比较准确性:通过key属性给元素标识,React可以更准确的比较元素,找到正确的变化位置。

  4. 不同类型元素替换渲染:如果新旧两棵树的某个位置对应的元素类型不同,React会销毁旧的子树并重新构造新的子树。

  5. 状态提高渲染效率:React会记录元素的状态,通过状态来判断是否需要重新渲染该元素。

  6. 事件监听保持不变:如果元素类型不同但有相同的key,React会复用原有元素的事件监听器。

10. 说说你对redux中间件的理解?常用的中间件有哪些?实现原理?

Redux中间件的理解:redux是介于应用系统和系统软件之间的一类软件,使用系统软件提供的基础服务,衔接网络上应用系统的各个部分或者不同应用,从而达到资源共享,功能共享的目的。

常用中间件:redux-thunk用于异步操作中间件,redux-logger用于日志记录。

实现原理:所有的中间件都放在到数组中嵌套执行,判断传递过来的数据类型,最后执行dispath中间件内的middleware api可以拿到getSate和dispath的方法。

11. 如何使用css实现一个三角形,写出两种以上方案得满分?

方案一:使用 border 属性

.triangle {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
}

方案二:使用 transform 属性

.triangle {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
  transform: rotate(45deg);
}

12. 什么是强缓存和协商缓存?

强缓存:浏览器不会向服务器发送请求,直接向本地存储中读取数据并返回state code 200 协商缓存:浏览器向服务器发送请求,服务器根据浏览器传递的请求判断是否命中协商缓存,如果命中,服务器会返回给浏览器一个reponse,浏览器去本地存储中读取文件

13. 说说React jsx转换成真实DOM的过程?

  1. 解析:React会使用Babel等工具将JSX代码解析为JavaScript对象。

  2. 创建元素:解析后的JSX代码会被转换为React元素对象。React元素是一个普通的JavaScript对象,包含有关组件类型、属性和子元素的信息。

  3. 调和:React会将元素与之前的渲染结果进行比较,找出需要更新的部分,然后生成更新的操作。

  4. 渲染:React将生成的更新操作应用于真实的DOM,以保持UI与组件状态的同步。React使用虚拟DOM(Virtual DOM)来提高渲染性能,避免不必要的DOM操作。

14. 说说你对@reduxjs/toolkit的理解?和react-redux有什么区别?

react-redux 是的官方 React UI 绑定层,允许您的 React 组件从 Redux 存储中读取数据,并将操作分派到存储以更新状态。 @reduxjs/toolkit 是对 Redux 的二次封装,开箱即用可的一个高效的 Redux 开发工具集,使得创建store、更新store更加方便

15. React render方法的原理,在什么时候会触发?

render 方法的原理如下:

首次渲染:当一个组件被创建并插入到 DOM 中时,React 会调用该组件的 render 方法来生成组件的虚拟 DOM(Virtual DOM)树。然后,React 会将这个虚拟 DOM 树转换成真实的 DOM 树,并插入到页面的相应位置上。

更新渲染:当组件的状态(state)或属性(props)发生变化时,React 会自动调用组件的 render 方法重新生成新的虚拟 DOM 树。然后,React 会通过比较新旧虚拟 DOM 树的差异,将变化的部分更新到真实的 DOM 树上,从而更新页面的显示。

render 方法在以下情况下会触发:

  1. 组件首次渲染时,会调用组件的 render 方法生成初始的虚拟 DOM 树。

  2. 组件的状态(state)发生变化时,会重新调用组件的 render 方法生成新的虚拟 DOM 树,并通过比较差异更新页面显示。

  3. 组件的属性(props)发生变化时,会重新调用组件的 render 方法生成新的虚拟 DOM 树,并通过比较差异更新页面显示。

16. React性能优化的手段有哪些?

(1)使用纯组件

(2)路由懒加载

(3)避免使用内联样式属性

(4)优化react中的条件渲染

(5)列表渲染的时候加key

(6)类组件使用immutable 减少渲染次数

(7)React Fragments避免额外标签

(8)React.memo:缓存组件渲染,避免不必要的更新

(9)使用PureComponent或shouldComponentUpdate:PureComponent会实现一个浅对比的shouldComponentUpdate(),可以避免不必要的重新渲染。 对于复杂的state,可以手动实现shouldComponentUpdate(),进行深度对比,避免跳过必要的重新渲染,同时提高不必要重新渲染的判断精度。

17. 如何通过原生js实现一个节流函数和防抖函数,写出核心代码,不是简单的思路?

  1. 节流函数:

function throttle(func, delay) {
    let timer = null;
    return function() {
        if (!timer) {
            timer = setTimeout(() => {
                func.apply(this, arguments);
                timer = null;
            }, delay);
        }
    };
}
  1. 防抖函数:

function debounce(func, delay) {
    let timer = null;
    return function() {
        clearTimeout(timer);
        timer = setTimeout(() => {
            func.apply(this, arguments);
        }, delay);
    };
}

18. 说说webpack中代码分割如何实现?

手动配置代码分割:通过在 webpack 配置文件中手动配置代码分割的规则。可以使用 entry 配置项指定入口文件,使用 output 配置项指定输出文件名,然后使用 optimization.splitChunks 配置项来指定代码分割的规则。

动态导入(Dynamic Import):在代码中使用动态导入语法来实现代码分割。动态导入可以通过 import() 函数来实现

使用第三方库:一些第三方库已经内置了代码分割的功能,例如 React 的 React.lazy()React.Suspense,Vue 的 Vue Router 等。通过使用这些库提供的功能,可以方便地实现代码分割。

19. 说说如何借助webpack来优化前端性能?

  1. 代码压缩和混淆:Webpack 可以使用 UglifyJSPlugin 或 TerserPlugin 来压缩和混淆代码,减小文件体积,提高加载速度。

  2. 代码分割:通过配置 Webpack 的 SplitChunksPlugin 或动态导入语法 (Dynamic Import) 来实现代码分割,将代码拆分成更小的块,按需加载,减少初始加载的文件大小。

  3. 懒加载和按需加载:使用动态导入语法 (Dynamic Import) 或第三方库(如 React.lazy 和 Vue Router)来实现懒加载和按需加载,只在需要时才加载相应的模块,减少初始加载的资源。

  4. 缓存优化:通过为生成的文件添加哈希值来解决浏览器缓存问题,确保文件内容发生变化时,浏览器能够正确地获取到最新的文件。

  5. Tree Shaking:使用 Webpack 的 Tree Shaking 功能,可以剔除未使用的代码,减少文件体积。

  6. 图片优化:使用 file-loader 或 url-loader 配合 image-webpack-loader 对图片进行压缩和优化,减小图片文件大小,提高加载速度。

  7. 编译缓存:使用 Webpack 的缓存功能,通过配置 cache-loader 或 hard-source-webpack-plugin,可以缓存编译过的模块,提高构建速度。

  8. 并行构建:使用 Webpack 的 parallel-webpack 或 happypack 插件,可以实现多线程并行构建,加快构建速度。

20. 说说javascript内存泄漏的几种情况?

  1. 无意的全局变量:在全局作用域中定义的变量会一直存在于内存中,直到页面关闭。如果不小心声明了一个全局变量,并且忘记在后续代码中清除它,就会造成内存泄漏。

  2. 被遗忘的定时器或回调函数:定时器(setTimeout、setInterval)和回调函数(addEventListener、Promise)在不再需要时,需要手动清除。如果忘记清除定时器或回调函数,它们将继续存在于内存中,导致内存泄漏。

  3. 闭包:闭包是指一个函数访问了其外部函数的变量,而这个函数又被保留在外部作用域中。如果闭包中引用了大量的变量或者引用了 DOM 元素,但不再需要使用它们,就会导致内存泄漏。

  4. DOM 引用:如果在 JavaScript 中保留了对 DOM 元素的引用,而这些元素在后续的操作中被删除或替换,但是引用没有被清除,就会导致内存泄漏。例如,通过事件监听器或全局变量持有对 DOM 元素的引用,如果没有及时移除监听器或清除全局变量,就会引起内存泄漏。

  5. 循环引用:当两个或多个对象之间形成循环引用时,即使它们没有被其他部分引用,也无法被垃圾回收机制回收。这种情况下,需要手动打破循环引用,以便垃圾回收机制可以正确释放内存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值