前端面试(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的比较

目录
相关文章
|
14天前
|
安全 编译器 PHP
PHP 8.x:让老将焕发新活力
PHP 8.x:让老将焕发新活力
155 76
|
14天前
|
机器学习/深度学习 人工智能 缓存
CALM自编码器:用连续向量替代离散token,生成效率提升4倍
近年来语言模型效率优化多聚焦参数规模与注意力机制,却忽视了自回归生成本身的高成本。CALM提出新思路:在token之上构建潜在空间,通过变分自编码器将多个token压缩为一个连续向量,实现“一次前向传播生成多个token”。该方法大幅减少计算次数,提升推理速度与吞吐量,同时引入无似然训练与BrierLM评估体系,突破传统语言建模范式,为高效大模型提供新路径。
90 7
CALM自编码器:用连续向量替代离散token,生成效率提升4倍
|
19天前
|
机器学习/深度学习 人工智能 搜索推荐
构建AI智能体:七十一、模型评估指南:准确率、精确率、F1分数与ROC/AUC的深度解析
本文系统介绍了机器学习模型评估的核心指标与方法。首先阐述了混淆矩阵的构成(TP/FP/FN/TN),并基于此详细讲解了准确率、精确率、召回率和F1分数的计算原理和适用场景。特别指出准确率在不平衡数据中的局限性,强调精确率(减少误报)和召回率(减少漏报)的权衡关系。然后介绍了ROC曲线和AUC值的解读方法,说明如何通过调整分类阈值来优化模型性能。最后总结了不同业务场景下的指标选择策略:高精度场景侧重精确率,高召回场景关注召回率,平衡场景优选F1分数,不平衡数据则推荐使用AUC评估。
227 20
|
14天前
|
人工智能 监控 Cloud Native
云原生AI赋能文旅数智化转型:玄晶引擎AI数字员工落地长白山康养项目全解析
本文以长白山大健康企业为例,介绍其通过玄晶引擎云原生AI数字员工实现“养生+文旅”模式智能化升级的实践。涵盖技术架构、运营适配、营销创新与落地经验,展现AI在内容生产、客服转化、B端获客等环节的全链路赋能,助力企业收益率提升47%、团队扩张35%,为文旅产业数智化转型提供可复用范本。
106 12
|
15天前
|
人工智能 缓存 监控
Coze AI 智能体工作流:配置与实战完整指南
本文详细介绍了如何利用Coze平台的工作流功能构建智能AI助手。通过解析核心组件并演示“个性化旅行规划师”的完整配置案例,文章展示了如何设计并行处理、集成外部工具并优化性能。重点探讨了工作流的模块化设计、版本控制及成本优化等进阶技巧,旨在帮助用户将AI从简单工具转变为能处理复杂任务、甚至具备自学习能力的业务伙伴。
|
14天前
|
人工智能 自然语言处理 运维
2025 AI客服选型全景评测:从技术适配到价值赋能
伴随大语言模型与AI Agent技术的深度渗透,2025年智能客服行业完成了从“标准化问答工具”到“全场景智能服务中枢”的关键性跨越。这一转型不仅重构了客户服务的交互模式,更推动客服体系成为企业链接用户、优化运营的核心基础设施,其价值从单纯的成本节约延伸至业务增长赋能。
|
12天前
|
人工智能 开发框架 机器人
宝塔部署AstrBot及Napcat防踩坑教程
本教程详述了在宝塔面板11上,通过Docker容器部署AstrBot与Napcat,实现QQ机器人接入AI的全过程。内容涵盖环境搭建、关键配置(如容器网络互通、WebSocket连接及平台适配器设置)等。
宝塔部署AstrBot及Napcat防踩坑教程
|
4天前
|
机器学习/深度学习 人工智能 安全
构建AI智能体:八十六、大模型的指令微调与人类对齐:从知识渊博到善解人意
本文探讨了大模型从知识储备到实用助手的进化过程。首先分析了原始预训练模型存在的问题:擅长文本补全但缺乏指令理解能力,可能生成有害或无关内容。然后详细介绍了指令微调技术,通过高质量(指令-输出)数据集教会模型理解并执行翻译、总结、情感分析等任务。进一步阐述了人类对齐技术,包括基于人类反馈的强化学习(RLHF)的三个关键步骤,使模型输出不仅符合指令,更符合人类价值观。最后展示了Qwen模型微调实践,包括代码实现和效果对比。整个过程将AI从知识库转变为既强大又安全可靠的智能助手。
88 19
|
4天前
|
人工智能 测试技术 API
一线工程师 2025 总结:LLM 只用了不到 10%,剩下 90% 卡在哪?
2025年,LLM能力爆发,但多数企业仅用到其10%。真正瓶颈不在模型强弱,而在工程落地:延迟不可控、并发崩溃、换模成本高、成本失控成常态。当LLM从“工具”变为“基础设施”,中转层与系统稳定性成为关键。释放剩余90%潜力,需扎实的架构设计与工程治理。