如果你是一位有理想的前端开发人员,并且正在准备面试,那么这篇文章就是为你准备的。本文收集了React面试中最常见的50大问题,这是一份理想的指南,让你为React相关的面试做好充分的准备工作。首先我们快速了解一下React在市场上的需求和现状,然后再开始讨论React面试问题。
JavaScript工具的市场地位正在缓慢而稳定地上升当中,而对React认证的需求正在飞速增长。选择正确的技术来开发应用程序或网站变得愈加艰难。React被认为是Javascript语言中增长最快的框架。
虚拟DOM和可复用部件等独特特性吸引了前端开发人员的注意。尽管成熟的框架(如Angular、Meteor和Vue等)在MVC(模型-视图-控制器)中只是一个“视图”库,但它们都有很强的竞争力。下图显示了常见JS框架的趋势:
以下是面试官最有可能提出的50个面试问题和答案。
真实DOM | 虚拟DOM |
---|---|
1. 更新较慢 | 1. 更新较快 |
2. 可以直接更新HTML | 2. 不能直接更新HTML |
3. 元素更新时创建一个新DOM | 3. 元素更新时更新JSX |
4. DOM操作开销较大 | 4. DOM操作非常容易 |
5. 内存浪费严重 | 5. 没有内存浪费 |
React的一些主要优点包括:
下面列出了React的主要局限:
JSX是JavaScript XML的简写。这是React使用的一种文件类型,具备JavaScript的表现力,并使用HTML作为模板语法。这样一来HTML文件理解起来就非常简单。这种文件可以创造稳健的应用程序并提高其效率。下面是一个JSX实例:
render(){
return(
<div>
<h1> Hello World from Codersera!!</h1>
</div>
);
}
虚拟DOM是轻量级的JavaScript对象,一开始只是真实DOM的一个副本。它是一个节点树,将组件列为对象及其属性和内容的列表。React的渲染功能从React的各个部分生成一个节点树。然后,它会根据由不同用户或系统行为引起的信息模型突变来更新此树。
虚拟DOM的工作机制只有简单的三步组成。
1.每当任何基础信息更改时,整个UI就会以虚拟DOM的表示形式重新渲染。
2.然后计算先前的DOM表示和新的DOM表示之间的区别。
3.计算完成后,只有实际更改的内容才会更新到真实DOM。
React使用JSX(JavaScript eXtension),我们可以用它编写类似于HTML的JavaScript。但由于JSX不是合法的JavaScript,因此浏览器无法直接读取它。如果JavaScript文件包含JSX,则必须将其转换。你需要一个转换器将JSX转换为浏览器可以理解的常规Javascript。目前最常用的转换器是Babel。
ES5和ES6的语法区别如下:
// ES5
var React = require('react');
// ES6
import React from 'react';
******** export vs exports *********
// ES5
module.exports = Component;
// ES6
export default Component;
****** function *****
// ES5
var MyComponent = React.createClass({
render: function() {
return <h3> Hello CoderSera! </h3>
},
});
// ES6
class MyComponent extends React.Component {
render() {
return <h3> Hello CoderSera! </h3>
}
}
******* props ******
// ES5
var App = React.createClass({
propTypes: { name: React.PropTypes.string },
render: function() {
return <h3> Hello, { this.props.name }! < /h3>
},
});
// ES6
class App extends React.Component {
render() {
return <h3> Hello, { this.props.name }! </h3>
}
}
****** state *****
// ES5
var App = React.createClass({
getInitialState: function() {
return { name: 'world' };
}
render: function() {
return <h3> Hello, { this.state.name }! < /h3>;
},
});
// ES6
class App extends React.Component {
constructor() {
super();
this.state = { name: 'world' };
}
render() {
return <h3> Hello, { this.state.name }! < /h3>
}
render() {
return;
<h3> Hello, { this.state.name }! < /h3>
}
React对比Angular | React | Angular |
---|---|---|
1. 架构 | 使用虚拟DOM | 使用真实DOM |
2. 渲染 | 服务端渲染 | 客户端渲染 |
3. DOM | 使用虚拟DOM | 使用真实DOM |
4. 数据绑定 | 单向数据绑定 | 双向数据绑定 |
5. 调试 | 编译时调试 | 运行时调试 |
6. 开发者 | 谷歌 |
React应用程序的UI构建块都是组件。这些部分将整个UI划分为许多可自治和可复用的微小部分。然后独立的某个部分发生变化就不会影响UI的其余部分。
它被视为普通函数,但render()函数必须返回某些值,无论值是否为空。调用组件文件时默认会调用render()方法,因为组件需要显示HTML标记,或者我们可以说JSX语法。每个React组件必须有一个render()函数,它返回单个React元素,该元素代表原生DOM组件。如果需要渲染多个HTML元素,则必须将它们分组在一个封闭的标签内,如form
、group
和div
等。此函数必须保持纯净,就是说它在每次调用时必须返回相同的结果。
import React, { Component } from 'react';
class App extends Component {
render() {
return (<div> <h1 className='App-title'> hello CoderSera </h1></div>)
}
}
export default App;
Hooks是一项新功能,使你无需编写类即可使用状态等React功能。来看一个useState hook示例。
<em>import </em>{useState} <em>from </em>'react';<br><br><em>function </em>Example() {<br> <em>// Declare a new
组件可以通过状态来跟踪其执行的任何渲染之间的信息。
状态用于可变数据或将要更改的数据。这对于用户输入尤其方便。以搜索栏为例,用户输入数据时他们看到的内容也会更新。
条件 | 状态 | Props |
---|---|---|
1. 从父组件接收初始值 | 是 | 是 |
2. 父组件可以更改值 | 否 | 是 |
3. 在组件内设置默认值 | 是 | 是 |
4. 在组件内更改 | 是 | 否 |
5. 为子组件设置初始值 | 是 | 是 |
6. 在子组件内更改 | 否 | 是 |
可以使用this.setState()更新组件的状态。
class MyComponent extends React.Component {
constructor() {
super();
this.state = {
name: 'Maxx',
id: '101'
}
}
render()
{
setTimeout(()=>{this.setState({name:'Jaeha', id:'222'})},2000)
return (
<div>
<h1>Hello {this.state.name}</h1>
<h2>Your Id is {this.state.id}</h2>
</div>
);
}
}
ReactDOM.render(
<MyComponent/>, document.getElementById('content')
);
粗箭头=>用于定义匿名函数,这通常是将参数传递给回调函数的最简单方法。但是你需要在使用它时优化性能。注意:每次渲染组件时,在render方法中使用箭头函数都会创建一个新函数,这可能会影响性能。
//General way
render() {
return(
<MyInput onChange={this.handleChange.bind(this) } />
);
}
//With Arrow Function
render() {
return(
<MyInput onChange={ (e) => this.handleOnChange(e) } />
);
}
有状态组件 | 无状态组件 |
---|---|
1. 在内存中存储组件状态更改的信息 | 1. 计算组件的内部状态 |
2. 有权更改状态 | 2. 无权更改状态 |
3. 包含过去、现在和可能的未来状态更改的信息 | 3. 没有包含关于状态更改的信息 |
4. 无状态组件通知它们关于状态更改的需求,然后它们将props传递给前者 | 4. 它们从有状态组件接收props,将其视为回调函数 |
React组件的生命周期分为三个不同阶段:
一些最重要的生命周期方法包括:
在React中,事件是对特定动作(如鼠标悬停、鼠标单击和按键等)触发的反应。处理这些事件类似于处理DOM元素上的事件。但是在语法上存在一些差异,例如:
事件参数包含一组特定于事件的属性。每个事件类型都包含它自己的属性和行为,这些属性和行为只能通过它的事件处理程序访问。
class Display extends React.Component({
show(evt) {
// code
},
render() {
// Render the div with an onClick prop (value is a function)
return (
<div onClick={this.show}>Click Me!</div>
);
}
});
合成事件是围绕浏览器原生事件充当跨浏览器包装器的对象。它们将不同的浏览器行为合并为一个API。这样做是为了确保在各个浏览器的事件中显示一致的特征。
Ref是React引用的简写。它是一个属性,帮助存储对特定元素或组件的引用,由组件渲染的配置函数返回。它用于返回对渲染返回的特定元素或组件的引用。当我们需要DOM测量或向组件添加方法时,它们会派上用场。
class ReferenceDemo extends React.Component{
display() {
const name = this.inputDemo.value;
document.getElementById('disp').innerHTML = name;
}
render() {
return(
<div>
Name: <input type="text" ref={input => this.inputDemo = input} />
<button name="Click" onClick={this.display}>Click</button>
<h2>Hello <span id="disp"></span> !!!</h2>
</div>
);
}
}
以下是应使用ref的情况:
可以使用export和import属性来模块化软件。它们有助于在不同的文档中单独编写组件。
//ChildComponent.jsx
export default class ChildComponent extends React.Component {
render() {
return( <div>
<h1>This is a child component</h1>
</div>)
}
}
//ParentComponent.jsx
import ChildComponent from './childcomponent.js';
class ParentComponent extends React.Component {
render() {
return(
<div>
<App />
</div>
);
}
}
React提供了一种有状态的,响应式的方法来构建表单。与其他DOM元素不同,HTML表单元素在React中的工作机制有所不同。例如,表单数据通常由组件而不是DOM处理,并且通常使用受控组件来实现。
区别在于可以使用回调函数来处理表单事件,然后使用容器的状态存储表单数据。这使你的组件可以更好地控制表单控制元素和表单数据。
回调函数是在发生事件(包括更改表单控制值或表单提交)时触发的。
handleSubmit(event) {
alert('A name was submitted: ' + this.state.value);
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>
Name:
<input type="text" value={this.state.value} onChange={this.handleSubmit} />
</label>
<input type="submit" value="Submit" />
</form>
);
}
受控组件 | 非受控组件 |
---|---|
1. 它们不维护自己的状态 | 1. 它们维护自己的状态 |
2. 数据由父组件控制 | 2. 数据由DOM控制 |
3. 它们通过props获得当前值,然后通过回调通知更改 | 3. 使用引用来获得它们的当前值 |
React中的高阶组件是一种在组件之间共享通用功能而无需重复代码的模式。
高阶组件实际上不是组件,它是一个接受组件并返回新组件的函数。它将一个组件转换为另一个组件,并添加其他数据或功能
HOC可用于许多任务,例如:
React并没有在我们的组件中编写shouldComponent方法,而是引入了一个带有内置shouldComponentUpdate实现的新组件,它是React.PureComponent组件。
React.PureComponent通过浅层prop和状态比较来实现它。在某些情况下,你可以使用React.PureComponent来提高性能。
键可帮助React识别哪些项目已更改、添加或删除。应该为数组内的元素提供键,以赋予元素稳定的身份。键必须是唯一的。
当使用动态创建的组件或用户更改列表时,React键非常有用。设置键值后,更改后的组件就能保持唯一标识。
以下是MVC框架的一些主要问题:
Flux是Facebook内部与React搭配使用的架构。它不是框架或库。只是一种新型的体系结构,是对React和单向数据流概念的补充:
Flux的各个组成部分如下:
Redux是一种状态管理工具。尽管它主要与React搭配使用,但也可以与其他任何JavaScript框架或库搭配。
Redux允许你在一个称为存储(Store)的对象中管理整个应用程序状态。
对存储的更新将触发与存储的已更新部分连接的组件的重新渲染。当我们想要更新某些东西时,我们称之为动作(Action)。我们还创建函数来处理这些动作并返回更新的存储。这些函数称为Reducer。
单一可信来源:整个应用程序的状态存储在单个存储区中的对象/状态树中。单一状态树使我们能更容易地跟踪历史更改,更方便地调试或检查应用程序。
状态是只读的:更改状态的唯一方法是触发动作。动作是描述更改的普通JS对象。就像状态是数据的最小表示一样,动作是数据更改的最小表示。
使用纯函数更改:为了确认动作是如何转换状态树的,你需要纯函数。纯函数是返回值仅取决于其参数值的函数。
单一可信源(SSOT)是构造信息模型和相关数据模式的实践,其中每个数据元素都只能在一个地方掌握(或编辑)
Redux使用“存储”将应用程序的整个状态存储在一个位置。因此,组件的所有状态都存储在存储中,并且存储本身会接收更新。单一状态树使我们能更容易地跟踪历史更改,更方便地调试或检查应用程序。
Redux由以下组件组成:
React中的动作必须具有type属性,该属性指示正在执行的ACTION的类型。必须将它们定义为字符串常量,你也可以为其添加更多属性。在Redux中使用称为“动作创建者”的函数来创建动作。以下是动作和动作创建者的示例:
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
Reducer是用于指示ACTION反应中应用程序状态变化的简单功能。它接收先前的状态和动作,然后返回新的状态。它根据动作类型确定需要哪种更新,然后返回新值。如果没有要完成的工作,它将按原样返回先前状态。
存储是一个JavaScript对象,可以保存应用程序的状态,并提供一些辅助方法来访问状态、调度动作并记录侦听器。应用程序的整个状态/对象树存储在单个存储中。因此Redux非常容易理解且可预测。我们可以将中间件转移到存储,以管理数据处理任务,并维护更改存储状态的各种活动的日志。通过Reducer,所有活动都返回新的状态。
Flux | Redux |
---|---|
1. 存储包括状态和更改逻辑 | 1. 存储和更改逻辑是分离的 |
2. 有多个存储 | 2. 只有一个存储 |
3. 所有存储不互通,是平行的 | 3. 带有分层Reducer的单个存储 |
4. 有单个调度器 | 4. 没有调度器的概念 |
5. React组件订阅到存储 | 5. 容器组件是有联系的 |
6. 状态是可变的 | 6. 状态是不可变的 |
Redux的优点如下:
React Router是建立在React之上的功能强大的路由库。它使URL与网页上显示的数据保持同步。它保持标准化的结构和行为,可用于开发单页Web应用程序。React Router有一个简单的API。React Router提供了一种方法,只会显示你的应用中路由匹配你的定义的那些组件。
在Switch组件内,Route和Redirect组件嵌套在内部。从Switch顶部的Route/Redirect组件开始到底部的Route/Redirect,根据浏览器中当前的URL是否与Route/Redirect组件的prop/路径匹配,将每个组件评估为true或false。
Switch只会渲染第一个匹配的子级。当我们嵌套了下面这样的路由时真的很方便:
<Switch>
<Route path="/accounts/new" component={AddForm} />
<Route path={`/accounts/:accountId`} component={Profile} />
</Switch>
路由器用于定义多个路由,并且当用户键入特定的URL时,如果该URL与路由器内部定义的任何“路由”的路径匹配,则该用户将被重定向到该路由。因此我们需要在应用程序中添加一个路由器库,以允许创建多个路由,每个路由都为我们指向一个独特的视图。
从React Router包导入的组件有两个属性,一个是将用户引导到指定路径的path,另一个是用于定义所述路径中内容的component。
<switch>
<route exact path=’/’ component={Home}/>
<route path=’/posts/:id’ component={Newpost}/>
<route path=’/posts’ component={Post}/>
</switch>
几个优点是:
传统路由 | React路由 | |
---|---|---|
参与的页面 | 每个视图对应一个新页面 | 只涉及单个HTML页面 |
URL更改 | 向服务器发送一个HTTP请求并接收对应的HTML页面 | 只有历史属性被更改 |
体验 | 用户其实是在每个视图的不同页面间切换 | 用户以为自己正在不同的页面间切换 |
原文链接: https://codersera.com/blog/top-50-react-questions-you-need-to-prepare-for-the-interview-in-2019/
领取专属 10元无门槛券
私享最新 技术干货