前端react面试题详细解答

指出(组件)生命周期方法的不同

  • componentWillMount – 多用于根组件中的应用程序配置
  • componentDidMount – 在这可以完成所有没有 DOM 就不能做的所有配置,并开始获取所有你需要的数据;如果需要设置事件监听,也可以在这完成
  • componentWillReceiveProps – 这个周期函数作用于特定的 prop 改变导致的 state 转换
  • shouldComponentUpdate – 如果你担心组件过度渲染,shouldComponentUpdate 是一个改善性能的地方,因为如果组件接收了新的 prop, 它可以阻止(组件)重新渲染。shouldComponentUpdate 应该返回一个布尔值来决定组件是否要重新渲染
  • componentWillUpdate – 很少使用。它可以用于代替组件的 componentWillReceivePropsshouldComponentUpdate(但不能访问之前的 props)
  • componentDidUpdate – 常用于更新 DOM,响应 prop 或 state 的改变
  • componentWillUnmount – 在这你可以取消网络请求,或者移除所有与组件相关的事件监听器

fetch封装

npm install whatwg-fetch --save  // 适配其他浏览器
npm install es6-promiseexport const handleResponse = (response) => {if (response.status === 403 || response.status === 401) {const oauthurl = response.headers.get('locationUrl');if (!_.isEmpty(oauthUrl)) {window.location.href = oauthurl;return;}}if (!response.ok) {return getErrorMessage(response).then(errorMessage => apiError(response.status, errorMessage));}if (isJson(response)) {return response.json();}if (isText(response)) {return response.text();}return response.blob();
};const httpRequest = {request: ({method, headers, body, path, query,}) => {const options = {};let url = path;if (method) {options.method = method;}if (headers) {options.headers = {...options.headers,...headers};}if (body) {options.body = body;}if (query) {const params = Object.keys(query).map(k => `${k}=${query[k]}`).join('&');url = url.concat(`?${params}`);}return fetch(url, Object.assign({}, options, { credentials: 'same-origin' })).then(handleResponse);},
};export default httpRequest;

React-Router 4怎样在路由变化时重新渲染同一个组件?

当路由变化时,即组件的props发生了变化,会调用componentWillReceiveProps等生命周期钩子。那需要做的只是: 当路由改变时,根据路由,也去请求数据:

class NewsList extends Component {componentDidMount () {this.fetchData(this.props.location);}fetchData(location) {const type = location.pathname.replace('/', '') || 'top'this.props.dispatch(fetchListData(type))}componentWillReceiveProps(nextProps) {if (nextProps.location.pathname != this.props.location.pathname) {this.fetchData(nextProps.location);} }render () {...}
}
复制代码

利用生命周期componentWillReceiveProps,进行重新render的预处理操作。

React.forwardRef是什么?它有什么作用?

React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中。这种技术并不常见,但在以下两种场景中特别有用:

  • 转发 refs 到 DOM 组件
  • 在高阶组件中转发 refs

React的状态提升是什么?使用场景有哪些?

React的状态提升就是用户对子组件操作,子组件不改变自己的状态,通过自己的props把这个操作改变的数据传递给父组件,改变父组件的状态,从而改变受父组件控制的所有子组件的状态,这也是React单项数据流的特性决定的。官方的原话是:共享 state(状态) 是通过将其移动到需要它的组件的最接近的共同祖先组件来实现的。 这被称为“状态提升(Lifting State Up)”。

概括来说就是将多个组件需要共享的状态提升到它们最近的父组件上在父组件上改变这个状态然后通过props分发给子组件。

一个简单的例子,父组件中有两个input子组件,如果想在第一个输入框输入数据,来改变第二个输入框的值,这就需要用到状态提升。

class Father extends React.Component {constructor(props) {super(props)this.state = {Value1: '',Value2: ''}}value1Change(aa) {this.setState({Value1: aa})}value2Change(bb) {this.setState({Value2: bb})}render() {return (<div style={{ padding: "100px" }}><Child1 value1={this.state.Value1} onvalue1Change={this.value1Change.bind(this)} /><Child2 value2={this.state.Value1} /></div>)}
}
class Child1 extends React.Component {constructor(props) {super(props)}changeValue(e) {this.props.onvalue1Change(e.target.value)}render() {return (<input value={this.props.Value1} onChange={this.changeValue.bind(this)} />)}
}
class Child2 extends React.Component {constructor(props) {super(props)}render() {return (<input value={this.props.value2} />)}
}ReactDOM.render(<Father />,document.getElementById('root')
)
复制代码

React.Children.map和js的map有什么区别?

JavaScript中的map不会对为null或者undefined的数据进行处理,而React.Children.map中的map可以处理React.Children为null或者undefined的情况。

React 中的高阶组件运用了什么设计模式?

使用了装饰模式,高阶组件的运用:

function withWindowWidth(BaseComponent) {class DerivedClass extends React.Component {state = {windowWidth: window.innerWidth,}onResize = () => {this.setState({windowWidth: window.innerWidth,})}componentDidMount() {window.addEventListener('resize', this.onResize)}componentWillUnmount() {window.removeEventListener('resize', this.onResize);}render() {return <BaseComponent {...this.props} {...this.state}/>}}return DerivedClass;
}
const MyComponent = (props) => {return <div>Window width is: {props.windowWidth}</div>
};
export default withWindowWidth(MyComponent);
复制代码

装饰模式的特点是不需要改变 被装饰对象 本身,而只是在外面套一个外壳接口。JavaScript 目前已经有了原生装饰器的提案,其用法如下:

@testableclass MyTestableClass {}

类的key改了,会发生什么,会执行哪些周期函数?

在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。

答:componentWillMount componentDidMount render

React中constructor和getInitialState的区别?

两者都是用来初始化state的。前者是ES6中的语法,后者是ES5中的语法,新版本的React中已经废弃了该方法。

getInitialState是ES5中的方法,如果使用createClass方法创建一个Component组件,可以自动调用它的getInitialState方法来获取初始化的State对象,

var APP = React.creatClass ({getInitialState() {return { userName: 'hi',userId: 0};}
})
复制代码

React在ES6的实现中去掉了getInitialState这个hook函数,规定state在constructor中实现,如下:

Class App extends React.Component{constructor(props){super(props);this.state={};}}
复制代码

为什么 React 要用 JSX?

JSX 是一个 JavaScript 的语法扩展,或者说是一个类似于 XML 的 ECMAScript 语法扩展。它本身没有太多的语法定义,也不期望引入更多的标准。

其实 React 本身并不强制使用 JSX。在没有 JSX 的时候,React 实现一个组件依赖于使用 React.createElement 函数。代码如下:

class Hello extends React.Component {render() {return React.createElement('div',null, `Hello ${this.props.toWhat}`);}
}
ReactDOM.render(React.createElement(Hello, {toWhat: 'World'}, null),document.getElementById('root')
);
复制代码

而 JSX 更像是一种语法糖,通过类似 XML 的描述方式,描写函数对象。在采用 JSX 之后,这段代码会这样写:

class Hello extends React.Component {render() {return <div>Hello {this.props.toWhat}</div>;}
}
ReactDOM.render(<Hello toWhat="World" />,document.getElementById('root')
);
复制代码

通过对比,可以清晰地发现,代码变得更为简洁,而且代码结构层次更为清晰。

因为 React 需要将组件转化为虚拟 DOM 树,所以在编写代码时,实际上是在手写一棵结构树。而XML 在树结构的描述上天生具有可读性强的优势。

但这样可读性强的代码仅仅是给写程序的同学看的,实际上在运行的时候,会使用 Babel 插件将 JSX 语法的代码还原为 React.createElement 的代码。

总结: JSX 是一个 JavaScript 的语法扩展,结构类似 XML。JSX 主要用于声明 React 元素,但 React 中并不强制使用 JSX。即使使用了 JSX,也会在构建过程中,通过 Babel 插件编译为 React.createElement。所以 JSX 更像是 React.createElement 的一种语法糖。

React 团队并不想引入 JavaScript 本身以外的开发体系。而是希望通过合理的关注点分离保持组件开发的纯粹性。

为什么不直接更新 state 呢 ?

如果试图直接更新 state ,则不会重新渲染组件。

// 错误
This.state.message = 'Hello world';

需要使用setState()方法来更新 state。它调度对组件state对象的更新。当state改变时,组件通过重新渲染来响应:

// 正确做法
This.setState({message: ‘Hello World’});

对有状态组件和无状态组件的理解及使用场景

(1)有状态组件

特点:

  • 是类组件
  • 有继承
  • 可以使用this
  • 可以使用react的生命周期
  • 使用较多,容易频繁触发生命周期钩子函数,影响性能
  • 内部使用 state,维护自身状态的变化,有状态组件根据外部组件传入的 props 和自身的 state进行渲染。

使用场景:

  • 需要使用到状态的。
  • 需要使用状态操作组件的(无状态组件的也可以实现新版本react hooks也可实现)

总结: 类组件可以维护自身的状态变量,即组件的 state ,类组件还有不同的生命周期方法,可以让开发者能够在组件的不同阶段(挂载、更新、卸载),对组件做更多的控制。类组件则既可以充当无状态组件,也可以充当有状态组件。当一个类组件不需要管理自身状态时,也可称为无状态组件。

(2)无状态组件 特点:

  • 不依赖自身的状态state
  • 可以是类组件或者函数组件。
  • 可以完全避免使用 this 关键字。(由于使用的是箭头函数事件无需绑定)
  • 有更高的性能。当不需要使用生命周期钩子时,应该首先使用无状态函数组件
  • 组件内部不维护 state ,只根据外部组件传入的 props 进行渲染的组件,当 props 改变时,组件重新渲染。

使用场景:

  • 组件不需要管理 state,纯展示

优点:

  • 简化代码、专注于 render
  • 组件不需要被实例化,无生命周期,提升性能。 输出(渲染)只取决于输入(属性),无副作用
  • 视图和数据的解耦分离

缺点:

  • 无法使用 ref
  • 无生命周期方法
  • 无法控制组件的重渲染,因为无法使用shouldComponentUpdate 方法,当组件接受到新的属性时则会重渲染

总结: 组件内部状态且与外部无关的组件,可以考虑用状态组件,这样状态树就不会过于复杂,易于理解和管理。当一个组件不需要管理自身状态时,也就是无状态组件,应该优先设计为函数组件。比如自定义的 <Button/><Input /> 等组件。

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

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

react 的优化

shouldcomponentUpdate pureCompoment setState

  • CPU的瓶颈(当有大量渲染任务的时候,js线程和渲染线程互斥)
  • IO的瓶颈 就是网络(如何在网络延迟客观存在的 情况下,减少用户对网络延 迟的感知)(Code Splitting • Data Fetching)比如react.lazy(组件懒加载) suspense(分包在网络上,用的时候在获取)
  • Virtual DOM 快么(Virtual DOM的优势不在于单次的操作,而是在大量、频繁的数据更新下,能够对视图 进行合理、高效的更新。)

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

react 版本差异

react16.8 hooks

React 16之后有三个生命周期被废弃(但并未删除)

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

官方计划在17版本完全删除这三个函数,只保留UNSAVE_前缀的三个函数,目的是为了向下兼容,

react 16.4 新增

getSnapshotBeforeUpdate

getDerivedStateFromProps

对于废弃的生命周期函数,官方会采用逐步迁移的方式来实现版本的迁移:

16.3:为不安全的生命周期引入别名,UNSAFE_componentWillMount、UNSAFE_componentWillReceiveProps 和 UNSAFE_componentWillUpdate。(旧的生命周期名称和新的别名都可以在此版本中使用。)

未来 16.x 版本:为 componentWillMount、componentWillReceiveProps 和 componentWillUpdate 启用废弃告警。(旧的生命周期名称和新的别名都将在这个版本中工作,但是旧的名称在开发模式下会产生一个警告。)

17.0:删除 componentWillMount、componentWillReceiveProps 和 componentWillUpdate。(在此版本之后,只有新的 “UNSAFE_” 生命周期名称可以使用。)。

在 React 中如何处理事件

为了解决跨浏览器的兼容性问题,SyntheticEvent 实例将被传递给你的事件处理函数,SyntheticEvent是 React 跨浏览器的浏览器原生事件包装器,它还拥有和浏览器原生事件相同的接口,包括 stopPropagation()preventDefault()
比较有趣的是,React 实际上并不将事件附加到子节点本身。React 使用单个事件侦听器侦听顶层的所有事件。这对性能有好处,也意味着 React 在更新 DOM 时不需要跟踪事件监听器。

React组件的构造函数有什么作用?它是必须的吗?

构造函数主要用于两个目的:

  • 通过将对象分配给this.state来初始化本地状态
  • 将事件处理程序方法绑定到实例上

所以,当在React class中需要设置state的初始值或者绑定事件时,需要加上构造函数,官方Demo:

class LikeButton extends React.Component {constructor() {super();this.state = {liked: false};this.handleClick = this.handleClick.bind(this);}handleClick() {this.setState({liked: !this.state.liked});}render() {const text = this.state.liked ? 'liked' : 'haven\'t liked';return (<div onClick={this.handleClick}>You {text} this. Click to toggle.      </div>);}
}
ReactDOM.render(<LikeButton />,document.getElementById('example')
);
复制代码

构造函数用来新建父类的this对象;子类必须在constructor方法中调用super方法;否则新建实例时会报错;因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法;子类就得不到this对象。

注意:

  • constructor () 必须配上 super(), 如果要在constructor 内部使用 this.props 就要 传入props , 否则不用
  • JavaScript中的 bind 每次都会返回一个新的函数, 为了性能等考虑, 尽量在constructor中绑定事件

react面试题合集(附答案)相关推荐

  1. 历年计算机一级b考试试题及答案,全国计算机等级考试一级B历年试题合集含答案...

    好多原题 1. 全国计算机等级考试一级B历年试题合集含答案(CHM文件下载)>> (1)计算机的特点是处理速度快.计算精度高.存储容量大.可靠性高.工作全自动以及 A)造价低廉 B)便于大 ...

  2. React高频面试题总结 (附答案及原理代码)

    React高频面试题总结 (附答案及原理代码) 1.说说对React的理解?有哪些特性? 1.React是用于构建用户界面的JavaScript库,只提供了UI层面的解决方案,遵循组件设计模式.声明式 ...

  3. 大学“电路分析基础”试题合集第六章(文末附PDF文档与Word文档)

    大学"电路分析基础"试题合集第一章 大学"电路分析基础"试题合集第二章 大学"电路分析基础"试题合集第三章 大学"电路分析基础&q ...

  4. 2021金三最新自动化测试面试题合集(含答案)!

    金三已经过去了,相信很多小伙伴在为银四做准备,这里给大家整理了一些金三中有被问到的自动化测试面试题合集,希望会小伙伴们有所帮助! 需要面试题合集的小伙伴,可点击这里领取哦! web自动化测试: 1.S ...

  5. python面试题及答案-50道Python面试题集锦(附答案)

    原标题:50道Python面试题集锦(附答案) Python是目前编程领域最受欢迎的语言.在本文中,我将总结Python面试中最常见的50个问题.每道题都提供参考答案,希望能够帮助你在2019年求职面 ...

  6. 计算机考试中英文打字题,最新计算机信息技术(五笔及中英文打字测试试题合集...

    最新计算机信息技术(五笔及中英文打字测试试题合集,搜狗五笔切换中英文,万能五笔 中英文切换,电脑打字五笔和中英文怎么转换,万能五笔中英文切换快捷键,五笔输入法怎么切换中英文,打字测试,在线打字测试,书 ...

  7. 大学“电路分析基础”试题合集第一章

    "电路分析基础"试题合集第一章         答案见文末 一.单项选择题(在每个小题的4个备选答案中,选出一个正确答案,并将正确答案的号码填入提干的括号内.每小题2分,共40分) ...

  8. 2020中高级前端面试题合集

    2020中高级前端面试题合集 "全方位总结一下所遇到的面试题目,与大家共同学习,也是对自己的一次总结" 文章同步到我的公众号<前端小时>,欢迎大家关注! 01 前言 2 ...

  9. 大学必考计算机软件cad,大学CAD考试试题2017「附答案」

    大学CAD考试试题2017「附答案」 一.选择题 1.缺省的世界坐标系的简称是( ).D (A)CCS (B)UCS (C)UCS1 (D)WCS 2.设置"夹点"大小及颜色是在[ ...

最新文章

  1. DOS MD命令三种用法
  2. STM32分类及命名方法
  3. 免费报名丨网易、腾讯、唯品会等100位名企超资深营销增长官,约你闭门“搞事情”...
  4. 调用布尔变量java_关于java的参数的调用,还有布尔的理解,这有一段代码,我有些不太理解,希望能够帮我分析下,谢谢...
  5. C语言的“编译时多态”
  6. Python3自带HTTP文件传输服务(局域网文件共享)
  7. GetManifestResourceStream得到的Stream是null的解决
  8. mysql view在测试过程的应用
  9. 关于OPENGL与OPENGL ES的区别
  10. linux网络安装mysql_linux系统安装mysql
  11. RSA加密与签名的区别
  12. 特征的标准化和归一化
  13. 手机号空号检测的几点建议
  14. 前端工程师面试时自我介绍该如何做?
  15. 头歌-自己动手画CPU(第一关)-8位可控加减法器-Logisim
  16. 流利阅读 2019.1.8 Taylor Swift used facial recognition software to detect stalkers at LA concert
  17. 方面级情感分析(一)
  18. 转发页面,并且传参数,@click@dblclick冲突问题
  19. 太平洋电信首批通过SD-WAN Ready 2.0服务认证
  20. 当矩阵的秩小于未知数的个数时,方程组有无数个解;当矩阵的秩等于未知数的个数时,方程组只有零解。...

热门文章

  1. iOS获取设备信息和获取当前屏幕状态
  2. 超轻量级中文ocr,OcrLiteOnnx文字识别
  3. 服装购销管理软件哪个好,有推荐的吗?
  4. luogu P2053 [SCOI2007]修车
  5. lua string 库
  6. centos6关闭防火墙(zonealarm pro防火墙)
  7. WineQQ 转自 清风的网络空间
  8. 2019 大数据必备书籍推荐
  9. 海利普变频器电路图 HLP-A原理图 图纸pdf格式
  10. 在网页中 生成QQ在线临时对话框/聊天