【面试题】2023年最新前端面试题-react篇

2023-11-10

原文见:语雀(https://www.yuque.com/deepstates/interview/hia3k3

● 核心概念
○ 元素渲染、组件、props、state
○ refs:使用场景、如何创建、如何访问
○ 组件通信:父子、祖孙、兄弟组件通信
○ 生命周期、事件处理、条件渲染、列表的key、表单、状态提升、组合&继承

⭐️⭐️⭐️ 相关知识参考:

说说你对react的理解?
是什么:react是构建用户界面的js库
能干什么:可以用组件化的方式构建快速响应的web应用程序
如何干:声明式(jsx) 组件化(方便拆分和复用 高内聚 低耦合) 一次学习随处编写
做的怎么样: 优缺(社区繁荣 一次学习随处编写 api简介)缺点(没有系统解决方案 选型成本高 过于灵活)
设计理念:跨平台(虚拟dom) 快速响应(异步可中断 增量更新)
性能瓶颈:cpu io fiber时间片 concurrent mode
渲染过程:scheduler render commit Fiber架构

React有什么特点?
● 声明式设计:react采用范式声明,开发者只需要声明显示内容,react就会自动完成
● 高效: react通过对dom的模拟(也就是虚拟dom),最大限度的减少与dom的交互
● 灵活: react可以和已知的库或者框架很好配合
● 组件: 通过react构建组件,让代码更容易复用,能够很好应用在大型项目开发中,把页面功能拆分成小模块 每个小模块就是组件
● 单向数据流: react是单向数据流,数据通过props从父节点传递到子节点,如果父级的某个props改变了,react会重新渲染所有的子节点

列出React的一些主要优点?

  1. 通过虚拟 DOM 提高应用程序的性能。
  2. JSX 使代码易于阅读和编写。
  3. 它在客户端和服务器端都能进行渲染(SSR)。
  4. 易于与框架(Angular, Backbone)集成,因为它只是一个视图库。
  5. 使用 Jest 等工具容易编写单元和集成测试。

React有哪些限制?

  1. React 只是一个视图库,不是一个完整的框架。
  2. 对于刚接触网络开发的初学者来说,有一个学习曲线。
  3. 将 React 整合到传统的 MVC 框架中需要一些额外的配置。
  4. 代码的复杂性随着内联模板和 JSX 的增加而增加。
  5. 太多的小组件导致了过度工程化或模板化。

如何模块化 React 中的代码?
可以使用export、import属性来模块化代码。它们有助于在不同的文件中单独编写组件。

对 React-Intl 的理解,它的工作原理?
● React-intl是雅虎的语言国际化开源项目FormatJS的一部分,通过其提供的组件和API可以与ReactJS绑定。
● React-intl提供了两种使用方法,一种是引用React组件,另一种是直接调取API,官方更加推荐在React项目中使用前者,只有在无法使用React组件的地方,才应该调用框架提供的API。它提供了一系列的React组件,包括数字格式化、字符串格式化、日期格式化等。
● 在React-intl中,可以配置不同的语言包,他的工作原理就是根据需要,在语言包之间进行切换。

区别

react vs vue?/ vue 与react的区别?(大华、阿里)
一、相同点:
● 都支持服务器渲染
● 都有虚拟dom,组件化开发,通过props参数进行父子组件数据的传递,都实现webcomponent规范
● 都是数据驱动视图
● 都有状态管理,react有redux,vue有vuex
● 都有支持native的方案 react有react native vue有weex
二、不同点:
● react严格上只针对mvc的view层,vue是mvvm模式
● 模板渲染方式不同
○ 模板的语法不同,React是通过jsx渲染,vue是通过一种拓展的html语法进行渲染。
○ 模板的原理不同:React是在组件JS代码中,通过原生JS实现模板中的常见语法,如插值、条件、循环等,都是通过JS语法实现的,更加纯粹更加原生。Vue是在和组件JS代码分离的单独的模板中,通过指令来实现的,比如条件语句就需要v-if来实现这一点。
● 虚拟dom不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个dom组件树,而react不同,当应用的状态被改变时,全部组件都会重新渲染,所以react中用shouldcomponentupdate这个生命周期的钩子函数来控制
● 组件写法不一样 ,react是jsx和inline style ,就是把html和css全写进js中,vue则是html,css ,js在同一个文件
● 数据绑定不一样,vue实现了数据双向绑定,react数据流动是单向的
● 在react中,state对象需要用setstate方法更新状态,在vue中,state对象不是必须的,数据由data属性在vue对象中管理

vue, react 适用场景? / vue, react 技术选型?
● 应用需要尽可能小和快就用vue, vue渲染速度比react 快
● 大型项目建议用react,因为vue模板的使用不容易发现错误、也不易拆分和测试
● 如果要适用于web 和原生app的项目,就使用react native

vue、react的区别和联系?()
vue, react的模板渲染、两者的虚拟dom、diff差异(vue2、vue3、react16)、两者的批量更新,还有路由差异、常用的优化手段、怎么进行数据通信、讲点新鲜的内容:vue3有什么特性、最后总结,谈谈两者的如今的生态。。。
React核心
核心概念
组件
你对组件的理解?
可组合,可复用,可维护,可测试

React声明组件有哪几种方法,有什么不同?/ React中有哪几种构建组件的方式?
一、React 声明组件的三种方式:
● 无状态函数式组件
○ 它是为了创建纯展示组件,这种组件只负责根据传入的props来展示,不涉及到state状态的操作
○ 组件不会被实例化,整体渲染性能得到提升,不能访问this对象,不能访问生命周期的方法
● ES5 原生方式 React.createClass定义的组件 // RFC
○ React.createClass会自绑定函数方法,导致不必要的性能开销,增加代码过时的可能性。
● ES6继承形式 extends React.Component定义的组件 // RCC
○ 目前极为推荐的创建有状态组件的方式,最终会取代React.createClass形式;相对于 React.createClass可以更好实现代码复用。
二、区别
1、无状态组件相对于于后者的区别:
(1)与无状态组件相比,React.createClass和React.Component都是创建有状态的组件,这些组件是要被实例化的,并且可以访问组件的生命周期方法。
2、React.createClass与React.Component区别:
(1)函数this自绑定
● React.createClass创建的组件,其每一个成员函数的this都有React自动绑定,函数中的this会被正确设置。
● React.Component创建的组件,其成员函数不会自动绑定this,需要开发者手动绑定,否则this不能获取当前组件实例对象。
(2)组件属性类型propTypes及其默认props属性defaultProps配置不同
● React.createClass在创建组件时,有关组件props的属性类型及组件默认的属性会作为组件实例的属性来配置,其中defaultProps是使用getDefaultProps的方法来获取默认组件属性的
● React.Component在创建组件时配置这两个对应信息时,他们是作为组件类的属性,不是组件实例的属性,也就是所谓的类的静态属性来配置的。
(3)组件初始状态state的配置不同
● React.createClass创建的组件,其状态state是通过getInitialState方法来配置组件相关的状态;
● React.Component创建的组件,其状态state是在constructor中像初始化组件属性一样声明的。

React 中构建组件的方式?
● 自定义组件:函数组件或者无状态组件 ,组件首字母大写
● 类组件:一个类组件必须实现一个render方法,这个方法必须返回一个jsx元素,要用一个外层的元素把所有内容包裹起来

你怎样理解“在React中,一切都是组件”这句话?

Component, Element, Instance 之间有什么区别和联系?
● 元素:一个元素element是一个普通对象(plain object),描述了对于一个DOM节点或者其他组件component,你想让它在屏幕上呈现成什么样子。元素element可以在它的属性props中包含其他元素(译注:用于形成元素树)。创建一个React元素element成本很低。元素element创建之后是不可变的。
● 组件:一个组件component可以通过多种方式声明。可以是带有一个render()方法的类,简单点也可以定义为一个函数。这两种情况下,它都把属性props作为输入,把返回的一棵元素树作为输出。
● 实例:一个实例instance是你在所写的组件类component class中使用关键字this所指向的东西(译注:组件实例)。它用来存储本地状态和响应生命周期事件很有用。
函数式组件(Functional component)根本没有实例instance。类组件(Class component)有实例instance,但是永远也不需要直接创建一个组件的实例,因为React帮我们做了这些。

如何有条件地向React组件添加属性?
对于某些属性,React非常聪明,如果传递给它的值是虚值,可以省略该属性。
var InputComponent = React.createClass({
render: function() {
var required = true;
var disabled = false;

return(
  <input type="text" disabled={disabled} required={required}>
)

}
})
渲染结果:

另一种可能的方法是:
var condition = true;

var component = (

有状态组件、无状态组件
区分有状态和无状态组件?
有状态组件 无状态组件
1、在内存中存储有关组件状态变化的信息 1、计算组件的内部的状态
2、有权改变状态 2、无权改变状态
3、包含过去、现在和未来可能的状态变化情况 3、不包含过去、现在和未来可能的状态变化情况
4、接收无状态组件状态变化要求的通知,然后将props发送给他们 4、从有状态组件接收props并将其视为回调函数

对有状态组件和无状态组件的理解及使用场景
一、有状态组件
1、特点:
● 是类组件
● 有继承
● 可以使用this
● 可以使用react的生命周期
● 使用较多,容易频繁触发生命周期钩子函数,影响性能
● 内部使用 state,维护自身状态的变化,有状态组件根据外部组件传入的 props 和自身的 state进行渲染。
2、使用场景:
● 需要使用到状态的。
● 需要使用状态操作组件的(无状态组件的也可以实现新版本react hooks也可实现)
3、总结:
类组件可以维护自身的状态变量,即组件的 state ,类组件还有不同的生命周期方法,可以让开发者能够在组件的不同阶段(挂载、更新、卸载),对组件做更多的控制。类组件则既可以充当无状态组件,也可以充当有状态组件。当一个类组件不需要管理自身状态时,也可称为无状态组件。
二、无状态组件
1、特点:
● 不依赖自身的状态state
● 可以是类组件或者函数组件。
● 可以完全避免使用 this 关键字。(由于使用的是箭头函数事件无需绑定)
● 有更高的性能。当不需要使用生命周期钩子时,应该首先使用无状态函数组件
● 组件内部不维护 state ,只根据外部组件传入的 props 进行渲染的组件,当 props 改变时,组件重新渲染。
2、使用场景:
● 组件不需要管理 state,纯展示
3、优点:
● 简化代码、专注于 render
● 组件不需要被实例化,无生命周期,提升性能。输出(渲染)只取决于输入(属性),无副作用
● 视图和数据的解耦分离
4、缺点:
● 无法使用 ref
● 无生命周期方法
● 无法控制组件的重渲染,因为无法使用shouldComponentUpdate 方法,当组件接受到新的属性时则会重渲染
三、总结:
组件内部状态且与外部无关的组件,可以考虑用状态组件,这样状态树就不会过于复杂,易于理解和管理。当一个组件不需要管理自身状态时,也就是无状态组件,应该优先设计为函数组件。比如自定义的 、 等组件。

函数组件、类组件
函数组件(Functional component,也称哑组件,或展示组件,或hooks组件)和类组件(Class component)的相同点和不同点?(税友)
一、相同点:都可以接收props返回react元素
二、不同点:
● 编程思想:类组件需要创建实例,面向对象,函数组件不需要创建实例,接收输入,返回输出,函数式编程
● 内存占用:类组建需要创建并保存实例,占用一定的内存
● 值捕获特性:函数组件具有值捕获的特性 。function组件能捕获渲染的值(captaure the rendered values),读取渲染闭包内的数据,而class组件在react通过this.的方式读取,this是可变的,所以总能获取最新的props
● 状态:类组件有自己的状态,函数组件没有,只能通过useState。Class把state属性挂载的对象保存到memoizedState属性中,而Function是用链表来保存状态的,memoizedState属性保存是链表的头指针。
● 生命周期:类组件有完整生命周期,函数组件没有,可以使用useEffect实现类似的生命周期
● 可测试性:函数组件方便测试
● 逻辑复用:类组件继承 Hoc(逻辑混乱 嵌套),组合优于继承,函数组件hook逻辑复用
● 跳过更新:shouldComponentUpdate PureComponent,React.memo
● 发展未来:函数组件将成为主流,屏蔽this、规范、复用,适合时间分片和渲染

类组件
为什么类方法需要绑定到类实例?
在JS中,this值会根据当前上下文变化。
在React类组件方法中,开发人员通常希望this引用组件的当前实例。因此有必要将这些方法绑定到实例。
通常,这是在构造函数中完成的。

在构造函数中调用super的目的是什么?/ 在构造函数调用super并将props作为参数传入的作用是啥?
在调用super()方法之前,子类构造函数无法使用this引用,子类必须在 constructor 中调用 super()。将props参数传递给super()调用的主要原因是在子构造函数中能够在constructor通过this.props来获取传入的props
● 传递props
class MyComponent extends React.Component {
constructor(props) {
super(props);
console.log(this.props); // { name: ‘sudheer’, age: 30 }
}
}
● 没传递props
class MyComponent extends React.Component {
constructor(props) {
super();
console.log(this.props); // undefined
// 但是Props参数仍然可用
console.log(props); // Prints { name: ‘sudheer’, age: 30 }
}

render() {
// 构造函数外部不受影响
console.log(this.props); // { name: ‘sudheer’, age: 30 }
}
}

渲染组件
UI组件、容器组件
展示组件(Presentational component)和容器组件(Container component)之间有何不同?
根据组件的职责通常把组件分为 UI 组件和容器组件。
UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。
两者通过 React-Redux 提供 connect 方法联系起来。

受控组件、非受控组件
何为受控组件(controlled component)?
React负责渲染表单的组件,值是来自于state控制的输入表单元素称为受控组件

你对受控组件和非受控组件了解多少? / 什么是受控组件? 什么是非受控组件?
● 受控组件是React控制中的组件,并且是表单数据真实的唯一来源。
● 非受控组件是由DOM处理表单数据的地方,而不是在React组件中。
尽管非受控组件通常更易于实现,因为只需使用refs即可从DOM中获取值,但通常建议优先选择受控制的组件,而不是非受控制的组件。
这样做的主要原因是受控组件支持即时字段验证,允许有条件地禁用/启用按钮,强制输入格式。
受控组件 非受控组件
1、没有维持自己的状态 1、保持着自己的状态
2、数据由父组件控制 2、数据由dom控制
3、通过props获取当前值,然后通过回调通知更改 3、refs用于获取当前值

props
区分状态(state)和 属性(props)?/ (组件的)状态(state)和属性(props)之间有何不同?
● Props是一个从外部传进组件的参数,主要作用就是父组件向子组件传递数据,但是props对于使用它的组件来说是只读的,一旦赋值不能修改,只能通过外部组件主动传入新的props来重新渲染子组件
● State 一个组件的显示形态可以由数据状态和外部参数决定,外部参数是props,数据状态就是state,首先,在组件初始化的时候,用this.state给组件设定一个初始的state,在第一次渲染的时候就会用这个数据来渲染组件,state不同于props一点是,state可以修改,通过this.setState()方法来修改state
条件 state props
从父组件中接收初始值 yes yes
从父组件可以改变值 no yes
在组件中设置默认值 yes yes
在组件的内部变化 yes no
设置子组件的初始值 yes yes
在子组件的内部更改 no yes

纯函数
什么是纯函数?
纯函数是不依赖并且不会在其作用域之外修改变量状态的函数。本质上,纯函数始终在给定相同参数的情况下返回相同结果。

state
React中的状态是什么?它是如何使用的?
状态是 React 组件的核心,是数据的来源,必须尽可能简单。基本上状态是确定组件呈现和行为的对象。与props 不同,它们是可变的,并创建动态和交互式组件。可以通过 this.state() 访问它们。

如何更新组件的状态
this.setState()、useState

当调用setState时,React render是如何工作的?
可以将render分为两个步骤
● 虚拟DOM渲染:当render方法被调用时,它返回一个新的组件的虚拟DOM结构。当调用setState()时,render会被再次调用,因为默认情况下shouldComponentUpdate总是返回true,所以默认情况下React是没有优化的。
● 原生DOM渲染:React只会在虚拟DOM中修改真实DOM节点,而且修改的次数非常少——这是很棒的React特性,它优化了真实DOM的变化,使React变得更快。

setState
调用 setState 之后发生了什么?
React在调用setstate后,react会将传入的参数对象和组件当前的状态合并,触发调和过程,
在调和过程中,react会根据新的状态构建react元素树重新渲染整个UI界面,在得到元素树之后,react会自动计算新老节点的差异,根据差异对界面进行最小化重新渲染

setState是同步的还是异步的?
一、setState 并不是单纯同步/异步的,它的表现会因调用场景的不同而不同:
● 在 React 钩子函数及合成事件中,它表现为异步;
● 同步:
○ DOM 原生事件中(绕过React通过addEventListener直接添加的事件处理函数)
○ 通过setTimeout/setInterval产生的异步调用
二、这种差异,本质上是由 React 事务机制和批量更新机制的工作方式来决定的:在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state。

为什么建议传递给 setState 的参数是一个 callback 而不是一个对象
因为在setstate中,props和state可能会异步更新,也就是说,对相同的变量进行处理的时候,会将这多次处理合并为一个,这个是批处理;而如果传入函数,那么会进行链式调用,这个函数会被react加入到一个执行队列中,函数中的代码会依次执行。

Refs

React 中 refs 的作用是什么?
Refs提供了一种访问在render方法中创建的 DOM 节点或者 React 元素的方法。在典型的数据流中,props是父子组件交互的唯一方式,想要修改子组件,需要使用新的pros重新渲染它。凡事有例外,某些情况下需要在典型数据流外,强制修改子代,这个时候可以使用Refs
class CustomForm extends Component {
handleSubmit = () => {
console.log("Input Value: ", this.input.value)
}
render () {
return (

<input
type=‘text’
ref={(input) => this.input = input} />
Submit

)
}
}
上述代码中的 input 域包含了一个 ref 属性,该属性声明的回调函数会接收 input 对应的 DOM 元素,我们将其绑定到 this 指针以便在其他的类函数中使用。
● refs 并不是类组件的专属,函数式组件同样能够利用闭包暂存其值:
function CustomForm ({handleSubmit}) {
let inputElement
return (
<form onSubmit={() => handleSubmit(inputElement.value)}>
<input
type=‘text’
ref={(input) => inputElement = input} />
Submit

)
}

列出一些应该使用 Refs 的情况?
1.需要管理焦点、选择文本或媒体播放时
2.触发式动画
3.与第三方 DOM 库集成

如何创建refs
● 回调函数
● React.createRef():refs是使用React.createRef()创建的,并通过ref属性附加到React元素。在构造组件时,通常将Refs分配给实例属性,以便可以在整个组件中引用它们
● useRef()

React如何获取组件对应的DOM元素?
可以用ref来获取某个子节点的实例,然后通过当前class组件实例的一些特定属性来直接获取子节点实例。ref有三种实现方法:
● 字符串格式:字符串格式,这是React16版本之前用得最多的,例如:

span


● 函数格式:ref对应一个方法,该方法有一个参数,也就是对应的节点实例,例如:<p ref={ele => this.info = ele}>
● createRef方法:React 16提供的一个API,使用React.createRef()来实现
● useRef

React中可以在render访问refs吗?为什么?
不可以,render 阶段 DOM 还没有生成,无法获取 DOM。DOM 的获取需要在 pre-commit 阶段和 commit 阶段。

组件通信
父子组件通信?
● 正向传值:父组件 -> 子组件
○ props
● 逆向传值:子组件 -> 父组件
○ props + 回调
● 订阅-发布
● redux

跨级组件方式?
● 逐层传值
○ 父 -> 子 -> 孙…,通过props往下传,通过回调往上传
● 跨级传值
○ context
● 订阅-发布
● redux

兄弟组件通信方式?
● 通过兄弟节点的共同父节点,由父节点转发消息
● 浏览器存储:使用sessionStorage、localStorage
● 路由传值:如果两个组件之间存在跳转,可以使用路由跳转赋值
● 订阅-发布
● redux

生命周期
react 生命周期函数有哪些不同阶段?
一、在组件生命周期中有4个不同的阶段:

  1. Initialzation 初始化状态:在这个阶段,组件准备设置初始化状态和默认属性
  2. Mounting:react组件已经准备好挂载到浏览器DOM中。这个阶段包括constructor、getDerivedStateFromProps、render、componentDidMount
  3. updating 更新阶段:在这个阶段,组件以两种方式更新,发送新的props和state状态。此阶段包括getDerivedStateFromProps、shouldComponentUpdate、render、getSnapshotBeforeUpdate、componentDidUpdate
  4. Unmounting 卸载阶段:在这个阶段,组件已经不再被需要了,它从浏览器DOM中卸载下来。这个阶段包含componentWillUnmount生命周期方法。
    二、还有一个错误处理的阶段
  5. Error Handling:在这个阶段,不论在渲染的过程中,还是在生命周期方法中,或是在任何子组件的构造函数中发生错误,该组件都会被调用。这个阶段包含了static getDerivedStateFromError()、componentDidCatch生命周期方法。

react生命周期方法有哪些?
一、React的生命周期中常用的有:
● constructor,负责数据初始化。
● render,将jsx转换成真实的dom节点。
● componentDidMount,组件第一次渲染完成时触发。可以在这里做AJAX请求,DOM的操作或状态更新以及设置事件监听器。
● componentDidUpdate,组件更新完成时触发。它主要用于更新DOM以响应props或state更改。
● componentWillUnmount,组件销毁和卸载时触发。它用于取消任何的网络请求,或删除与组件关联的所有事件监听器。
二、不常用的有:
● getDerivedStateFromProps,更新state和处理回调。
● shouldComponentUpdate,用于性能优化。
● getSnapshotBeforeUpdate,替代了componentWillUpdate。

render
怎样解释 React 中 render() 的目的?
每个React组件强制要求必须有一个 render()。它返回一个 React 元素,是原生 DOM 组件的表示。如果需要渲染多个 HTML 元素,则必须将它们组合在一个封闭标记内,例如、、

等。此函数必须保持纯净,即必须每次调用时都返回相同的结果

类组件的render方法执行后最终返回的结果是什么
jsx对象

怎么阻止组件渲染?
在组件的 render 方法中返回 null 并不会影响触发组件的生命周期方法

哪些方法会触发 React 重新渲染?重新渲染 render 会做些什么?
1)哪些方法会触发 react 重新渲染?
● setState()方法被调用
setState 是 React 中最常用的命令,通常情况下,执行 setState 会触发 render。但是这里有个点值得关注,执行 setState 的时候不一定会重新渲染。当 setState 传入 null 时,并不会触发 render。
class App extends React.Component {
state = {
a: 1
};

render() {
console.log(“render”);
return (
<React.Fragement>

{this.state.a}


<button
onClick={() => {
this.setState({ a: 1 }); // 这里并没有改变 a 的值
}}
>
Click me

<button onClick={() => this.setState(null)}>setState null

</React.Fragement>
);
}
}

● 父组件重新渲染
只要父组件重新渲染了,即使传入子组件的 props 未发生变化,那么子组件也会重新渲染,进而触发 render
(2)重新渲染 render 会做些什么?
● 会对新旧 VNode 进行对比,也就是我们所说的Diff算法。
● 对新旧两棵树进行一个深度优先遍历,这样每一个节点都会一个标记,在到深度遍历的时候,每遍历到一和个节点,就把该节点和新的节点树进行对比,如果有差异就放到一个对象里面
● 遍历差异对象,根据差异的类型,根据对应对规则更新VNode
React 的处理 render 的基本思维模式是每次一有变动就会去重新渲染整个应用。在 Virtual DOM 没有出现之前,最简单的方法就是直接调用 innerHTML。Virtual DOM厉害的地方并不是说它比直接操作 DOM 快,而是说不管数据怎么变,都会尽量以最小的代价去更新 DOM。React 将 render 函数返回的虚拟 DOM 树与老的进行比较,从而确定 DOM 要不要更新、怎么更新。当 DOM 树很大时,遍历两棵树进行各种比对还是相当耗性能的,特别是在顶层 setState 一个微小的修改,默认会去遍历整棵树。尽管 React 使用高度优化的 Diff 算法,但是这个过程仍然会损耗性能.

React如何判断什么时候重新渲染组件?
组件状态的改变可以因为props的改变,或者直接通过setState方法改变。组件获得新的状态,然后React决定是否应该重新渲染组件。只要组件的state发生变化,React就会对组件进行重新渲染。这是因为React中的shouldComponentUpdate方法默认返回true,这就是导致每次更新都重新渲染的原因。
当React将要渲染组件时会执行shouldComponentUpdate方法来看它是否返回true(组件应该更新,也就是重新渲染)。所以需要重写shouldComponentUpdate方法让它根据情况返回true或者false来告诉React什么时候重新渲染什么时候跳过重新渲染。

在React中如何避免不必要的render?
React 基于虚拟 DOM 和高效 Diff 算法的完美配合,实现了对 DOM 最小粒度的更新。大多数情况下,React 对 DOM 的渲染效率足以业务日常。但在个别复杂业务场景下,性能问题依然会困扰我们。此时需要采取一些措施来提升运行性能,其很重要的一个方向,就是避免不必要的渲染(Render)。这里提下优化的点:
● shouldComponentUpdate 和 PureComponent
在 React 类组件中,可以利用 shouldComponentUpdate或者 PureComponent 来减少因父组件更新而触发子组件的 render,从而达到目的。shouldComponentUpdate 来决定是否组件是否重新渲染,如果不希望组件重新渲染,返回 false 即可。
● 利用高阶组件
在函数组件中,并没有 shouldComponentUpdate 这个生命周期,可以利用高阶组件,封装一个类似 PureComponet 的功能
● 使用 React.memo
React.memo 是 React 16.6 新的一个 API,用来缓存组件的渲染,避免不必要的更新,其实也是一个高阶组件,与 PureComponent 十分类似,但不同的是, React.memo只能用于函数组件。

componentDidMount
应该在 React 组件的何处发起 Ajax 请求?
● 应该在componentDidMount函数中发起ajax请求。
● 原因:
○ 它在整个生命周期中只执行一次,避免了重复请求数据的情况。
○ 如果挂载组件之前获取到了数据请求结果,并在该组件上调用setState,这将不起作用,在componentDidMount中发起网络请求将保证这个组件可以更新。

shouldComponentUpdate
shouldComponentUpdate是做什么的
● 这个react生命周期函数是来解决这个问题:
在更新数据的时候用setState修改整个数据,数据变了之后,遍历的时候所有内容都要被重新渲染,数据量少还好,数据量大就会严重影响性能。
● 解决办法:

  1. shouldcomponentupdate 在渲染前进行判断组件是否更新,更新了再渲染
  2. purecomponent(纯组件)省去了虚拟dom生成和对比的过程 在类组件中使用
  3. react.memo() 类似于纯组件 在无状态组件中使用

getDerivedStateFromProps(原componentWillReceiveProps())
对componentWillReceiveProps 的理解
● 该方法当props发生变化时执行,初始化render时不执行,在这个回调函数里面,你可以根据属性的变化,通过调用this.setState()来更新你的组件状态,旧的属性还是可以通过this.props来获取,这里调用更新状态是安全的,并不会触发额外的render调用。
● 使用好处:在这个生命周期中,可以在子组件的render函数执行前获取新的props,从而更新子组件自己的state。可以将数据请求放在这里进行执行,需要传的参数则从componentWillReceiveProps(nextProps)中获取。而不必将所有的请求都放在父组件中。于是该请求只会在该组件渲染时才会发出,从而减轻请求负担。componentWillReceiveProps在初始化render的时候不会执行,它会在Component接受到新的状态(Props)时被触发,一般用于父组件状态更新时子组件的重新渲染

事件处理
React的事件和普通的HTML事件有什么不同?
一、区别:
● 对于事件名称命名方式,原生事件为全小写,react 事件采用小驼峰;
● 对于事件函数处理语法,原生事件为字符串,react 事件为函数;
● react 事件不能采用 return false 的方式来阻止浏览器的默认行为,而必须要地明确地调用preventDefault()来阻止默认行为。
二、合成事件是 react 模拟原生 DOM 事件所有能力的一个事件对象,其目的/优点如下:
● 兼容所有浏览器,更好的跨平台;
● 将事件统一存放在一个数组,避免频繁的新增与删除(垃圾回收)。
● 方便 react 统一管理和事务机制。
三、事件的执行顺序为原生事件先执行,合成事件后执行,合成事件会冒泡绑定到 document 上,所以尽量避免原生事件与合成事件混用,如果原生事件阻止冒泡,可能会导致合成事件不执行,因为需要冒泡到document 上合成事件才会执行。

React 中的箭头函数是什么?怎么用?
箭头函数(=>)是用于编写函数表达式的简短语法。这些函数允许正确绑定组件的上下文,因为在 ES6 中默认下不能使用自动绑定。使用高阶函数时,箭头函数非常有用。

合成事件
React中的合成事件是什么?
React基于Virtual DOM实现了一个SyntheticEvent层(合成事件层),定义的事件处理器会接收到一个合成事件对象的实例,它符合W3C标准,且与原生的浏览器事件拥有同样的接口,支持冒泡机制,所有的事件都自动绑定在最外层上。

React 事件机制 / 描述事件在React中的处理方式?/ 在React中如何处理事件?
● JSX 上写的事件并没有绑定在对应的真实 DOM 上,而是通过事件代理的方式,将所有的事件都统一绑定在了 document 上。这样的方式不仅减少了内存消耗,还能在组件挂载销毁时统一订阅和移除事件。
● React基于Virtual DOM实现了一个SyntheticEvent/sɪnˈθetɪk/层(合成事件层),定义的事件处理器会接收到一个合成事件对象的实例,它符合W3C标准,且与原生的浏览器事件拥有同样的接口,支持冒泡机制,React 实际上并没有将事件附加到子节点本身。React 将使用单个事件监听器监听顶层的所有事件。这对于性能是有好处的,这也意味着在更新 DOM 时,React 不需要担心跟踪事件监听器。

为什么不能用 return false 来阻止事件的默认行为?
早期使用的是return false,后期改为e.preventDefault(),因为return false会引起一些事件回调问题,这些回调会偶然返回错误(即没有意图阻止默认/停止传播)。

react处理事件冒泡?

事件代理
React 组件中怎么做事件代理?它的原理是什么?(网易)
一、React基于Virtual DOM实现了一个SyntheticEvent层(合成事件层),定义的事件处理器会接收到一个合成事件对象的实例,它符合W3C标准,且与原生的浏览器事件拥有同样的接口,支持冒泡机制,所有的事件都自动绑定在最外层上。
二、在React底层,主要对合成事件做了两件事:
● 事件委派:React会把所有的事件绑定到结构的最外层,使用统一的事件监听器,这个事件监听器上维持了一个映射来保存所有组件内部事件监听和处理函数。
● 自动绑定:React组件中,每个方法的上下文都会指向该组件的实例,即自动绑定this为当前组件

this
(在构造函数中)调用 super(props) 的目的是什么?
Super() 调用父类的构造方法,有super,组件才有自己的this,在组件全局中都可以使用this,如果只是constructor而不执行super,之后的this都是错的,super继承父组件的this

为什么我们的事件手动绑定this(不是箭头函数的情况)
事件监听函数在执行的时候会丢失上下文

修改this指向
方式1:在constructor中提前对事件进行绑定
方式2:通过bind方法进行原地绑定,从而改变this指向
方式3:通过创建箭头函数
方式4:将事件调用的写法改为箭头函数的形式

如何避免在React重新绑定实例? / 除了在构造函数中绑定 this,还有其它方式吗?
有几种常见方法可以避免在React中绑定方法:

  1. 将事件处理程序定义为内联箭头函数
    class SubmitButton extends React.Component {
    constructor(props) {
    super(props);
    this.state = {
    isFormSubmitted: false
    }
    }

render() {
return (
<button onClick={() => {
this.setState({isFormSubmitted: true})
}}>Submit</button
)
}
}
2. 使用箭头函数来定义方法
class SubmitButton extends React.Component {
state = {
isFormSubmitted: false
}

handleSubmit = () => {
this.setState({
isFormSubmitted: true
})
}

render() {
return (
Submit
)
}
}
3. 使用带Hooks的函数组件
const SubmitButton = () => {
const [isFormSubmitted, setIsFormSubmitted] = useState(false);

return(
<button onClick={() => {
setIsFormSubmitted(true);
}}>Submit
)
}

条件渲染
列表的key
React 中 key 的作用是什么?
Key用于识别唯一的 Virtual DOM 元素及其驱动 UI 的相应数。 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。

表单
如何在 React 中创建表单?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【面试题】2023年最新前端面试题-react篇 的相关文章

  • jQuery 中的 Javascript .files[0] 属性

    jQuery 中是否有与此语句等效的语句 var value document getElementById id files 0 使用附加 files 0 的标准 jQuery 选择器似乎不起作用 并且我找不到与 files 等效的 jQ
  • 如何使用键盘和鼠标控制相机 - Three.js

    我在 WEB GL 中有一个带有 Three js 的 3D 环境 并且我曾经使用 Orbitcontrols js http codepen io nireno pen cAoGI http codepen io nireno pen c
  • 有没有办法让 React 为孩子自动定义“键”?

    我正在学习 React 我偶然发现了 动态儿童 的这个怪癖 带有代码示例的序言 Render Pass 1
  • 限制文本区域中每行的字符数

    我整个周末都在寻找解决这个难题的方法 但尚未找到一个可以正常工作的解决方案 我想要实现的是限制文本区域中每行的字符数 不是相同地限制它们 而是我选择的每行不同的字符数 例如 我只想在我的文本区域中包含 4 行 第 1 2 和 3 行将限制为
  • 如何将中间件绑定到socket.io中的事件

    现在您可以将中间件绑定到io use middleware 但这仅在建立套接字连接时触发 有没有办法在将其传递给事件句柄之前拦截它 就像在expressjs中一样 换句话说 In 快递 js你可以做 app get middleware1
  • 计算Javascript中两次点击之间的时间

    我想用 javascript 计算属性的两次点击之间的时间 但我不知道如何 例如 a href click here a 如果用户单击多次 假设 5 秒内 我想显示警报 如果有帮助的话我正在使用 jQuery 我对 javascript 不
  • 保存/导出Chrome的JavaScript控制台输入历史记录

    无论如何 我可以保存或导出 JavaScript 控制台的历史记录吗 input 控制台历史记录 在 Google Chrome 中 我不想保存输出或错误 因此将鼠标悬停在控制台框上 右键单击并选择Save as 不是解决方案 我不想每次都
  • v-file-input .click() 不是函数

    我试图以编程方式触发 v file input 的 click 事件 因为它在 Vuetify 的文档中 但它显示一个错误this refs imagePicker click is not a function我在这里错过了什么吗 代码重
  • 如何将 Browserify 与外部依赖项一起使用?

    我正在尝试慢慢地将 Browserify 引入我的网站 但我不想重写所有 js 也不希望 jquery 和其他库的重复实例与我的 Browserify 版本捆绑在一起 如果我构建将 jquery 列为外部依赖项的模块 那么如何将其指向我的全
  • 如何在网页上实现文件上传进度条?

    当用户将文件上传到我的网络应用程序时 我想显示比动画 gif 更有意义的内容 我还有哪些可能性 编辑 我正在使用 Net 但我不介意是否有人向我展示与平台无关的版本 如果您对这一切在客户端通常如何工作感兴趣 就是这样 所有解决方案都通过 J
  • window.showModalDialog 的等效跨浏览器解决方案是什么?

    window showModalDialog 的等效跨浏览器解决方案有哪些 showModalDialog 在 IE 和 FF 3 中引入 我个人认为没有 但是有很多 UI 工具包提供了这样的功能 例如jQuery UI http jque
  • 加载另一个 JS 脚本后加载

    这是我的代码 very big js file lots of html stuff 问题是 这些是异步加载的 有没有办法等待第二个脚本直到第一个脚本加载 如果您使用 jQuery 有一个非常简单的方法可以通过获取脚本 https api
  • 如何将React版本17降级到16?

    由于 React 17 不支持许多 React 包 如何将 React 版本从 17 降级到 16 假设您使用 npm yarn 或其他节点包管理器 依赖项版本列在package json 搜索react and react dom包下de
  • 替换两个引号之间的字符串

    我想转动一根绳子str hello my name is michael what s your s into hello my name is span class name michael span 我怎样才能在 JavaScript
  • React Native - 跨屏幕传递数据

    我遇到了一些麻烦react native应用程序 我不知道如何跨屏幕传递数据 我意识到还有其他类似的问题在 SO 上得到了回答 但是这些解决方案对我来说不起作用 我正在使用StackNavigator 这是我的设置App js file e
  • Django 与谷歌图表

    我试图让谷歌图表显示在我的页面上 但我不知道如何将值从 django 视图传递到 javascript 以便我可以绘制图表 姜戈代码 array Year Sales Expenses 2004 1000 400 2005 1170 460
  • 如何修复超出最大调用堆栈大小

    有一个 MERN Firebase 应用程序并收到此错误和一堆 atdeepExtend deepCopy ts 71 RangeError Maximum call stack size exceeded getApps as apps
  • Restangular - _.contains() 不是一个函数

    如果您最近通过 Bower 更新了 Restangular 它将安装最新的 Lodash 新的 4 0 然而 这是一个问题 因为 Restangular Angular 现在会抛出错误 contains 不是函数 你怎么解决 解决方案非常简
  • 我可以使用 jQuery 动态创建文件(及其内容)吗? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 这是我的 HTML 代码 ul li
  • 在 javascript 中使用 xPath 解析具有默认命名空间的 XML

    我需要创建一个 XML xPath 解析器 所有解析都必须在客户端进行 使用 JavaScript 我创建了一个 javascript 来执行此操作 在默认名称空间发挥作用之前 一切看起来都正常 我根本无法查询具有默认命名空间的 XML 我

随机推荐

  • 敏捷开发知识体系笔记

    敏捷开发知识体系整体框架 敏捷开发工程实践 项目管理 迭代开发 风险价值生命周期 多级项目规划 完整团队 每日站立会议 任务板 燃尽图 需求管理 需求订单 业务流程草图 用例驱动开发 用户故事 架构 演进的架构 演进的设计 基于组件的架构设
  • 同步服务器安装系统,时间同步服务器的配置方法

    知道什么是时间同步服务器的配置方法吗 下面是学习啦小编跟大家分享的是时间同步服务器的配置方法 欢迎大家来阅读学习 时间同步服务器的配置方法 方法 步骤 双击任务栏右下角 时间 打开 时间和日期 属性 设置对话框 2选择 Internet时间
  • SimpleDateFormat用法详解

    SimpleDateFormat类是一个以语言环境敏感的方式来格式化和解析日期的工具类 它允许你将日期格式化为字符串 或从字符串解析为日期 格式化日期为字符串 SimpleDateFormat sdf new SimpleDateForma
  • 在linux下编译多线程需要如下设置

    编译时这样输入命令 gcc xxx c o xxx out lpthread
  • LeetCode知识点总结 - 1710

    LeetCode 1710 Maximum Units on a Truck 考点 难度 Sorting Easy 题目 You are assigned to put some amount of boxes onto one truck
  • Xilinx 7系FPGA LVDS使用要注意了,供电不能搞错

    最近新做了一块板子 用到Spartan 7芯片对前级视频源叠加OSD菜单 前级会将HMDI转成LVDS送给FPGA处理 在原理图设计阶段没有仔细阅读fpga手册 导致LVDS BANK供电错误 应该接2 5V 实际接3 3V 且BANK供电
  • 射频与无线技术入门 读书记录

    一 基础概念 无线系统框图 瓦特W 功率测量单位 能量 功率 时间 如100W的灯泡亮了2小时 能量就是100w 2 就是200W H的能量 波段 使用字母表示一定范围的频率 载波 载波只能使用模拟信号 在这个模拟信号上承载模拟或者数字信息
  • 跨域的解决方案

    一 跨域 1 概念 指的是浏览器不能执行其他网站的脚本 它是由浏览器的同源策略造成的 是 浏览器对javascript施加的安全限制 2 同源策略 是指协议 域名 端口都要相同 其中有一个不同都会产生跨域 3 跨域流程 二 解决跨域方案 1
  • [转载] 陈皓——程序员技术练级攻略

    PS 原文出自酷壳上的陈皓对程序员从入门到精通的攻略 让你感受一下真正的大神吧 又是阿里人 他的文章真心不错 希望对你也有用 原文地址 http coolshell cn articles 4990 html 陈皓酷壳博客地址 http c
  • oracle failover mode,Oracle RAC FailOver配置

    Oracle RAC FailOver配置 Oracle RAC主要为数据库的应用提供了HA High Available 的环境 HA体现在负载均衡 loadbalance 和容错 failover 两个方面 Oracle RAC 的Fa
  • 机器学习---期望+方差+标准差+协方差

    1 期望 在概率论和统计学中 数学期望 mathematic expectation 或均值 亦简称期望 是试验中每次可能结果的概率乘以其结果的总和 是最基本的数学特征之一 它反映随机变量平均取值的大小 大数定律表明 随着重复次数接近无穷大
  • Optimal Coin Change(完全背包计数)

    题目描述 In a 10 dollar shop everything is worthy 10 dollars or less In order to serve customers more effectively at the cas
  • Java对象序列化

    Java 对象序列化 对象序列化的目标是将对象保存到磁盘中 或允许在网络中直接传输对象 对象序列化机制允许把内存中的 java 对象转换成为与平台无关的二进制流 从而允许把这种二进制流持久保存到磁盘上 实现对象序列化 该类实现接口 seri
  • texstudio与ctex_Latex的使用(Ctex+TeXstudio)

    1 下载 CTEX Latex 本来是只支持英文的 但是实在太好用了 遂结合中国的团队以及有识之士 开发了这个 CTEX CTEX 有 TexLive TexLive 为 Latex 安装包的名字 的所有内容 还包括了中文的支持 所以这里我
  • 【C++】详解inline

    2023年8月28日 周一晚上 目录 优点 缺点 使用条件 为什么调用函数会有开销 举例说明 优点 当使用inline关键字声明一个函数时 编译器会将函数体内联到所有调用该函数的地方 这可以提高执行效率 因为无需进行函数调用的开销 缺点 但
  • android 日期控件

    相关布局文件
  • android:OKHttp的使用

    1 之前学习了两种基于http访问服务器的方法 一种是HttpURLConenction 一种是Apache下的HttpClient 说实话 这两种方法操作起来都不是很简单明了 所以当前首选的网络通信库是由Square公司开发的OKHttp
  • 有关C++,Qt中使用指针的注意事项

    1 指针一般在创建的时候都应该初始化 除非你能保证要么你不会用到这个指针 要么在你使用之前它以及被被初始化了 如果不初始化 它就是野指针 在Debug模式下 VC 编译器会把未初始化的栈内存上的指针全部填成 0xcccccccc 当字符串看
  • RUNOOB python练习题6 斐波那契数列

    用来练手的python 练习题其六 原链接 python练习实例6 题干 斐波那契数列 斐波那契数列可以说是很好的递归理解工具了 这里就用递归实现一下斐波那契数列 源代码如下 返回fibonacci数列中某一项的数值 def Fibonac
  • 【面试题】2023年最新前端面试题-react篇

    原文见 语雀 https www yuque com deepstates interview hia3k3 核心概念 元素渲染 组件 props state refs 使用场景 如何创建 如何访问 组件通信 父子 祖孙 兄弟组件通信 生命