前端面试(React框架一)

简介: React 是一个用于构建用户界面的 JavaScript 库,采用虚拟 DOM 提升渲染效率,支持组件化开发与服务端渲染,具有良好的性能优化机制和丰富的生命周期管理。

1.React框架

1. React 的优点有哪些?

Note

React 会创建一个虚拟 DOM(virtual DOM)。当一个组件中的状态改变时,React 首先会通过 "diffing" 算法来标记虚拟 DOM 中的改变,第二步是调节(reconciliation),会用 diff 的结果来更新 DOM。

  1. JSX 的引入,使得组件的代码更加可读,也更容易看懂组件的布局,或者组件之间是如何互相引用的
  2. 支持服务端渲染,可改进SEO和性能
  3. 易于测试
  4. React 只关注 View 层,所以可以和其它任何框架(如Backbone.js, Angular.js)一起使用

2. 说一下react的生命周期?

2.1 初始化阶段

  • getDefaultProps
  • 获取实例的默认属性
  • getInitialState
  • 获取每个实例的初始化状态
  • componentWillMount
  • 组件即将被装载、渲染到页面上
  • 多用于根组件中的应用程序配置
  • render
  • 组件在这里生成虚拟的DOM节点
  • componentDidMount
  • 组件真正在被装载之后
  • 在这可以完成所有没有 DOM 就不能做的所有配置,并开始获取所有你需要的数据(发送请求);如果需要设置事件监听,也可以在这完成

2.2 运行中状态

  • componentWillReceiveProps
  • 组件将要接收到属性的时候调用
  • shouldComponentUpdate
  • 是一个改善性能的地方,组件接受到新属性或者新状态的时候(可以返回false,接收数据后不更新,阻止render调用,后面的函数不会被继续执行了)
  • componentWillUpdate
  • 组件即将更新不能修改属性和状态
  • render
  • 组件重新描绘
  • componentDidUpdate
  • 组件已经更新
  • 响应 prop 或 state 的改变

2.3 销毁阶段

  • componentWillUnmount
  • 组件即将销毁
  • 在这你可以取消网络请求,或者移除所有与组件相关的事件监听器

Note

  1. react生命周期中,最适合与服务端进行数据交互的是哪个函数? componentDidMount:在这个阶段,实例和dom已经挂载完成,可以进行相关的dom操作
  2. (在构造函数中)调用 super(props) 的目的是什么
  • 在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。
  • 传递 props 给 super() 的原因则是让子类中能用 constructor 访问 this.props。

3. 对setState的理解?

3.1 当你调用setState的时候,发生了什么事?

  1. 将传递给 setState 的对象合并到组件的当前状态,触发所谓的调和过程(Reconciliation)
  2. 然后生成新的DOM树并和旧的DOM树使用Diff算法对比
  3. 根据对比差异对界面进行最小化重渲染

参考连接

3.2 setState第二个参数的作用

因为setState是一个异步的过程,所以说执行完setState之后不能立刻更改state里面的值。如果需要对state数据更改监听,setState提供第二个参数,就是用来监听state里面数据的更改,当数据更改完成,调用回调函数。

3.3 为什么建议传递给 setState 的参数是一个 callback 而不是一个对象

setState它是一个异步函数,他会合并多次修改,降低diff算法的比对频率。这样也会提升性能。

因为 this.props 和 this.state 的更新是异步的不能依赖它们的值去计算下一个 state。

3.4 react中key的作用(扩展)

key是React中用于追踪哪些列表中元素被修改、删除或者被添加的辅助标识。在diff算法中,key用来判断该元素节点是被移动过来的还是新创建的元素,减少不必要的元素重复渲染。

4. react中组件传值

  1. 父传子(组件嵌套浅):父组件定义一个属性,子组件通过this.props接收。
  2. 子传父:父组件定义一个属性,并将一个回调函数赋值给定义的属性,然后子组件进行调用传过来的函数,并将参数传进去,在父组件的回调函数中即可获得子组件传过来的值。

5. 在constructor中绑定事件函数的this指向

把一个对象的方法赋值给一个变量会造成this的丢失,所以需要绑定this,把绑定放在构造函数中可以保证只绑定一次函数,如果放在render函数中绑定this的话每次渲染都会去绑定一次this,那样是很耗费性能的。

Note

小技巧:在构造器constructor中绑定函数的this只需要绑定一次,在一定程度上提升了性能。

6. shouldComponentUpdate(nextProps, nextState)的作用?

  1. 当父组件被重新渲染时即render函数执行时,子组件就会默认被重新渲染,但很多时候是不需要重新渲染每一个子组件的。这时就可以使用 shouldComponentUpdate 来判断是否真的需要重新渲染子组件。仅仅一个判断,就可以节约很多的消耗。
  2. 所以对于父组件发生变化而子组件不变的情况,使用shouldComponentUpdate会提升性能。
shouldComponentUpdate(nextProps, nextState) {
    if(nextProps.content === this.props.content) {
        return false;
    } else {
        return true;
    }
}
Copy

7. PureComponent的作用?

  1. PureComponent内部帮我们实现了shouldComponentUpdate的比较,其他和Component一样。但是在shouldComponentUpdate进行的是一个浅比较,看看官方文档是怎么说的。
  2. 浅比较只比较第一层的基本类型和引用类型值是否相同
  3. 如果数据结构比较复杂,那么可能会导致一些问题,要么当你知道改变的时候调用forceUpdate,要么使用immutable来包装你的state

8. 展示组件(Presentational component)和容器组件(Container component)之间有何不同

  1. 展示组件关心组件看起来是什么。
  2. 展示专门通过 props 接受数据和回调,并且几乎不会有自身的状态,但当展示组件拥有自身的状态时,通常也只关心 UI 状态而不是数据的状态。
  3. 容器组件则更关心组件是如何运作的。
  4. 容器组件会为展示组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其作为回调提供给展示组件。容器组件经常是有状态的,因为它们是(其它组件的)数据源。

9. 类组件(Class component)和函数式组件(Functional component)之间有何不同

  1. 类组件不仅允许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态
  2. 当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 '无状态组件(stateless component)',可以使用一个纯函数来创建这样的组件。这种组件也被称为哑组件(dumb components)或展示组件

10 受控组件和非受控组件有什么区别?

10.1 受控组件

在HTML中,标签 inputtextareaselect的值的改变通常是根据用户输入进行更新。在React中,可变状态通常保存在组件的状态属性中,并且只能使用 setState() 更新,而呈现表单的React组件也控制着在后续用户输入时该表单中发生的情况,以这种由React控制的输入表单元素而改变其值的方式,称为:“受控组件”。

10.2 不受控组件

表单数据由DOM本身处理。即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用 ref 从DOM获取表单值)

11. 状态(state)和属性(props)之间有何不同?

  1. State是一种数据结构,用于组件挂载时所需的默认值。State可能会随着时间的推移而发生突变,但多数时候是作为用户事件行为的结果。
  2. props是组件的配置。props由父组件传递给子组件,就子组件而言,props是不可变的。组件不能改变自身props,但是可以把其他子组件的props防止一起管理。
  3. props也不仅仅是数据,回调函数也可以通过props传递。

12. 客户端渲染与服务端渲染

客户端渲染即普通的React项目渲染方式。

12.1 客户端渲染流程

  1. 浏览器发送请求
  2. 服务器返回HTML
  3. 浏览器发送bundle.js请求
  4. 服务器返回bundle.js
  5. 浏览器执行bundle.js中的React代码

Attention

因为时间在往返的几次网络请求中就耽搁了,而且因为CSR返回到页面的HTML中没有内容,就只有一个root空元素,页面内容是靠js渲染出来的,爬虫在读取网页时就抓不到信息,所以SEO不友好

12.2 SSR带来的问题

  1. React代码在服务器端执行,很大的消耗了服务器的性能
  2. 首屏加载时间过长
  3. SEO 不友好

12.3 React 同构时页面加载流程

  1. 服务端运行React代码渲染出HTML
  2. 浏览器加载这个无交互的HTML代码
  3. 浏览器接收到内容展示
  4. 浏览器加载JS文件
  5. JS中React代码在浏览器中重新执行

13. 应该在 React 组件的何处发起 Ajax 请求?

  1. 在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。
  2. 更重要的是,你不能保证在组件挂载之前 Ajax 请求已经完成,如果是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起作用。

14. 除了在构造函数中绑定 this,还有其它方式吗?

你可以使用属性初始值设定项(property initializers)来正确绑定回调,create-react-app 也是默认支持的。在回调中你可以使用箭头函数,但问题是每次组件渲染时都会创建一个新的回调。

15. 怎么阻止组件的渲染?

在组件的 render 方法中返回 null 并不会影响触发组件的生命周期方法

16. 前端路由原理

前端路由实现起来其实很简单,本质就是监听 URL 的变化,然后匹配路由规则,显示相应的页面,并且无须刷新页面。目前前端使用的路由就只有两种实现方式。

  • Hash 模式
  • History 模式

16.1 Hash 模式

www.test.com/#/ 就是 Hash URL,当 # 后面的哈希值发生变化时,可以通过 hashchange 事件来监听到 URL 的变化,从而进行跳转页面,并且无论哈希值如何变化,服务端接收到的 URL 请求永远是 www.test.com。

window.addEventListener('hashchange', () => {
  // ... 具体逻辑
})
Copy

16.2 History 模式

History 模式是 HTML5 新推出的功能,主要使用 history.pushState history.replaceState 改变 URL。

通过 History 模式改变 URL 同样不会引起页面的刷新,只会更新浏览器的历史记录。

// 新增历史记录
history.pushState(stateObject, title, URL)
// 替换当前历史记录
history.replaceState(stateObject, title, URL)
Copy

当用户做出浏览器动作时,比如点击后退按钮时会触发 popState 事件

window.addEventListener('popstate', e => {
  // e.state 就是 pushState(stateObject) 中的 stateObject
  console.log(e.state)
})
Copy

16.3 两种模式对比

  1. Hash 模式只可以更改 # 后面的内容,History 模式可以通过 API 设置任意的同源 URL
  2. History 模式可以通过 API 添加任意类型的数据到历史记录中,Hash 模式只能更改哈希值,也就是字符串
  3. Hash 模式无需后端配置,并且兼容性好。History 模式在用户手动输入地址或者刷新页面的时候会发起 URL 请求,后端需要配置 index.html 页面用于匹配不到静态资源的时候

17. class和createClass的比较

目录
相关文章
|
17天前
|
人工智能 缓存 自然语言处理
LLM多跳推理深度测试:四项指标精准定位模型的推理极限
本文探讨大模型在多步推理中的表现,通过四项压力测试对比Llama 3.2与Qwen 3的逻辑极限。分析揭示:Llama 3.2依赖预训练内化的直觉推理,稳定高效;Qwen 3则靠“自我对话”推进复杂任务,虽具思考深度但易受算术错误影响,深层推理易崩溃。两者适用于不同场景——速度优先选Llama,探索性任务可试Qwen。
161 12
LLM多跳推理深度测试:四项指标精准定位模型的推理极限
|
1天前
|
SQL Java 数据库连接
蓝易云:MyBatis的配置文件中定义类型别名(type aliases)的技巧。
类型别名提供了一种便捷的方式来引用复杂的全限定类名。通过使用 <package>标签进行自动扫描或使用 <typeAlias>标签手动指定,可以在整个MyBatis配置中提高清晰度和维护性。无论
41 20
|
22天前
|
安全 IDE 开发工具
Python类型注解:让代码更清晰可维护
Python类型注解:让代码更清晰可维护
194 144
|
18天前
|
存储 缓存 数据建模
StarRocks + Paimon: 构建 Lakehouse Native 数据引擎
12月10日,Streaming Lakehouse Meetup Online EP.2重磅回归,聚焦StarRocks与Apache Paimon深度集成,探讨Lakehouse Native数据引擎的构建。活动涵盖架构统一、多源联邦分析、性能优化及可观测性提升,助力企业打造高效实时湖仓一体平台。
272 39
|
2月前
|
监控 安全 Unix
iOS 崩溃排查不再靠猜!这份分层捕获指南请收好
从 Mach 内核异常到 NSException,从堆栈遍历到僵尸对象检测,阿里云 RUM iOS SDK 基于 KSCrash 构建了一套完整、异步安全、生产可用的崩溃捕获体系,让每一个线上崩溃都能被精准定位。
594 70
|
8天前
|
人工智能 前端开发 测试技术
Violit: Streamlit杀手,无需全局刷新,构建AI快捷面板
Violit 是新一代 Python Web 框架,融合 Streamlit 的简洁语法与 React 的响应式性能。首创 O(1) 信号状态架构,零重运行、无需 `@cache`/`key`/回调,支持桌面原生应用与 30+ 主题,开箱即用、极速如光。
108 15
|
25天前
|
SQL 人工智能 分布式计算
从工单、文档到结构化知识库:一套可复用的 Agent 知识采集方案
我们构建了一套“自动提取 → 智能泛化 → 增量更新 → 向量化同步”的全链路自动化 pipeline,将 Agent 知识库建设中的收集、提质与维护难题转化为简单易用的 Python 工具,让知识高效、持续、低门槛地赋能智能体。
290 36
|
7天前
|
机器学习/深度学习 计算机视觉 网络架构
YOLO26改进 - 注意力机制 |融合HCF-Net维度感知选择性整合模块DASI 增强小目标显著性
本文介绍将HCF-Net中的维度感知选择性融合(DASI)模块集成至YOLO26检测头,通过通道分区与Sigmoid自适应加权,融合高/低维及当前层特征,显著提升红外小目标检测精度,在SIRST数据集上超越主流方法。(239字)
|
23天前
|
弹性计算 网络协议
阿里云服务器e实例ECS经济型99元一年,ecs.e-c1m1.large性能测评
阿里云99元/年服务器ECS经济型e实例,2核2G、3M固定带宽、40G ESSD云盘,新老用户均可购买,续费同价。性能稳定,支持WordPress等应用,独立IP不限流量,活动持续至2027年,限时抢购中。
|
1天前
|
Web App开发 监控 API
蓝易云:WebRTC中RTCPeerConnection对象的实践应用讨论。
总结起来,RTCPeerConnection提供了一个灵活、高效、安全的方式来实现实时的点对点通信。其在现代Web应用中的应用范围非常广泛,无论是简单的视频聊天应用,还是复杂的实时协作工具和互动娱乐服务,RTCPeerConnection都是构建这些解决方案的基础。开发者必须熟练掌握RTCPeerConnection的工作原理和API使用,才能构建出既高效又可靠的WebRTC应用。
45 23