2021年React常见的面试题以及答案(持续更新中

  • react组件之间如何通信

  • 什么是高阶组件?

  • 说说对React Hooks的理解?解决了什么问题?

  • 说说react中引入css的方式有哪几种?区别?

  • 在React中组件间过渡动画如何实现?

  • React context是什么?

  • 说说你对Redux的理解?其工作原理?

  • Redux遵循的三个原则是什么?

  • 数据如何通过 Redux 流动?

  • react-redux的两个最主要功能?

  • Redux中异步的请求怎么处理

  • 介绍Redux中间件

  • 你在React项目中是如何使用Redux的? 项目结构是如何划分的?

  • 为什么 React Router 中使用 Switch 关键字 ?

说说对React的理解?有哪些特性?

=================================================================================

是什么?

React,用于构建用户界面的 JavaScript 库,提供了 UI 层面的解决方案,遵循组件设计模式、声明式编程范式和函数式编程概念,以使前端应用程序更高效,使用虚拟DOM来有效地操作DOM,遵循从高阶组件到低阶组件的单向数据流,帮助我们将界面成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,构成整体页面.

特性

  • JSX语法

  • 单向数据绑定

  • 虚拟DOM

  • 声明式编程

  • Component(组件化)

优势

  • 高效灵活

  • 声明式的设计,简单使用

  • 组件式开发,提高代码复用率

  • 单向响应的数据流会比双向绑定的更安全,速度更快

区分Real DOM和Virtual DOM

=====================================================================================

Real DOM

  • Real DOM,真实DOM, 意思为文档对象模型,是一个结构化文本的抽象,在页面渲染出的每一个结点都是一个真实DOM结构

  • 更新缓慢

  • 可以直接更新 HTML

  • 如果元素更新,则创建新DOM

  • DOM操作代价很高

  • 消耗的内存较多

Virtual DOM

  • Virtual Dom,本质上是以 JavaScript 对象形式存在的对 DOM 的描述。创建虚拟DOM目的就是为了更好将虚拟的节点渲染到页面视图中,虚拟DOM对象的节点与真实DOM的属性一一照应

  • 更新更快

  • 无法直接更新 HTML

  • 如果元素更新,则更新 JSX

  • DOM 操作非常简单

  • 很少的内存消耗

什么是JSX和它的特性?

===========================================================================

JSX 是JavaScript XML的缩写,不是html或xml,基于ECMAScript的一种新特性,一种定义带属性树结构的语法;

特性:

  • 自定义组件名首字母大写

  • 嵌套;在render函数中return返回的只能包含一个顶层标签,否则也会报错。

  • 求值表达式;JSX基本语法规则,遇到HTML标签(以<开头),就用HTML规则解析;遇到代码块(以{开头),就用JS规则解析

  • 驼峰命名

  • class属性需要写成className

  • JSX允许直接在模板插入JS变量。如果这个变量是一个数组,则会展开这个数组的所有成员

  • 在JSX中插入用户输入是安全的,默认情况下ReactDOM会在渲染前,转义JSX中的任意值,渲染前,所有的值都被转化为字符串形式,这能预防XSS攻击。

类组件和函数组件之间有什么区别?

===============================================================================

类组件:

  • 无论是使用函数或是类来声明一个组件,它决不能修改它自己的 props。

  • 所有 React 组件都必须是纯函数,并禁止修改其自身 props。

  • React是单项数据流,父组件改变了属性,那么子组件视图会更新。

  • 属性 props是外界传递过来的,状态 state是组件本身的,状态可以在组件中任意修改

  • 组件的属性和状态改变都会更新视图。

函数组件:

  • 函数组件接收一个单一的 props 对象并返回了一个React元素

  • 函数组件的性能比类组件的性能要高,因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。

了解 Virtual DOM 吗?解释一下它的工作原理。

===========================================================================================

Virtual DOM 是一个轻量级的 JavaScript 对象,它最初只是 real DOM 的副本。它是一个节点树,它将元素、它们的属性和内容作为对象及其属性。 React 的渲染函数从 React 组件中创建一个节点树。然后它响应数据模型中的变化来更新该树,该变化是由用户或系统完成的各种动作引起的。

Virtual DOM 工作过程有三个简单的步骤:

  1. 每当底层数据发生改变时,整个 UI 都将在 Virtual DOM 描述中重新渲染。

  2. 然后计算之前 DOM 表示与新表示的之间的差异。

  3. 完成计算后,将只用实际更改的内容更新 real DOM。

说说对 State 和 Props的理解,有什么区别?

==========================================================================================

State

  • 一个组件的显示形态可以由数据状态和外部参数所决定,而数据状态就是state,一般在 constructor 中初始化

  • 当需要修改里面的值的状态需要通过调用setState来改变,从而达到更新组件内部数据的作用,并且重新调用组件render方法

  • setState还可以接受第二个参数,它是一个函数,会在setState调用完成并且组件开始重新渲染时被调用,可以用来监听渲染是否完成

Props

  • React的核心思想就是组件化思想,页面会被切分成一些独立的、可复用的组件,组件从概念上看就是一个函数,可以接受一个参数作为输入值,这个参数就是props,所以可以把props理解为从外部传入组件内部的数据

  • react具有单向数据流的特性,所以他的主要作用是从父组件向子组件中传递数据

  • props除了可以传字符串,数字,还可以传递对象,数组甚至是回调函数

  • 在子组件中,props在内部不可变的,如果想要改变它看,只能通过外部组件传入新的props来重新渲染子组件,否则子组件的props和展示形式不会改变

相同点

  • 两者都是 JavaScript 对象

  • 两者都是用于保存信息

  • props 和 state 都能触发渲染更新

区别

  • props 是外部传递给组件的,而 state 是在组件内被组件自己管理的,一般在 constructor 中初始化

  • props 在组件内部是不可修改的,但 state 在组件内部可以进行修改

  • state 是多变的、可以修改

说说对React refs 的理解?应用场景?

======================================================================================

是什么

React 中的 Refs提供了一种方式,允许我们访问 DOM节点或在 render方法中创建的 React元素。

本质为ReactDOM.render()返回的组件实例,如果是渲染组件则返回的是组件实例,如果渲染dom则返回的是具体的dom节点。

如何使用

  • 传入字符串,使用时通过 this.refs.传入的字符串的格式获取对应的元素

  • 传入对象,对象是通过 React.createRef() 方式创建出来,使用时获取到创建的对象中存在 current 属性就是对应的元素

  • 传入函数,该函数会在 DOM 被挂载时进行回调,这个函数会传入一个 元素对象,可以自己保存,使用时,直接拿到之前保存的元素对象即可

  • 传入hook,hook是通过 useRef() 方式创建,使用时通过生成hook对象的 current 属性就是对应的元素

应用场景

在某些情况下,我们会通过使用refs来更新组件,但这种方式并不推荐,过多使用refs,会使组件的实例或者是DOM结构暴露,违反组件封装的原则;

但下面的场景使用refs非常有用:

  • 对Dom元素的焦点控制、内容选择、控制

  • 对Dom元素的内容设置及媒体播放

  • 对Dom元素的操作和对组件实例的操作

  • 集成第三方 DOM 库

setState是同步还是异步

==============================================================================

setState本身并不是异步,之所以会有一种异步方法的表现形式,归根结底还是因为react框架本身的性能机制所导致的。因为每次调用setState都会触发更新,异步操作是为了提高性能,将多个状态合并一起更新,减少re-render调用。

实现同步:

  • setState提供了一个回调函数供开发者使用,在回调函数中,我们可以实时的获取到更新之后的数据。

state = {

number:1

};

componentDidMount(){

this.setState({number:3},()=>{

console.log(this.state.number) // 3

})

}

  • 利用setTimeout

state = {

number:1

};

componentDidMount(){

setTimeout(()=>{

this.setState({number:3})

console.log(this.state.number) //3

},0)

}

  • 还有在原生事件环境下

state = {

number:1

};

componentDidMount() {

document.body.addEventListener(‘click’, this.changeVal, false);

}

changeVal = () => {

this.setState({

number: 3

})

console.log(this.state.number) //3

}

super()和super(props)有什么区别?

=========================================================================================

在ES6中,通过extends关键字实现类的继承,super关键字实现调用父类,super代替的是父类的构建函数,使用super(xx)相当于调用sup.prototype.constructor.call(this.xx),如果在子类中不使用super关键字,则会引发报错

super()就是将父类中的this对象继承给子类的,没有super()子类就得不到this对象

在React中,类组件是基于es6的规范实现的,继承React.Component,因此如果用到constructor就必须写super()才初始化this,在调用super()的时候,我们一般都需要传入props作为参数,如果不传进去,React内部也会将其定义在组件实例中,所以无论有没有constructor,在render中this.props都是可以使用的,这是React自动附带的,但是也不建议使用super()代替super(props),因为在React会在类组件构造函数生成实例后再给this.props赋值,所以在不传递props在super的情况下,调用this.props为undefined,而传入props的则都能正常访问,确保了 this.props 在构造函数执行完毕之前已被赋值,更符合逻辑

总结

  • 在React中,类组件基于ES6,所以在constructor中必须使用super

  • 在调用super过程,无论是否传入props,React内部都会将porps赋值给组件实例porps属性中

  • 如果只调用了super(),那么this.props在super()和构造函数结束之间仍是undefined

说说对React事件机制的理解?

===============================================================================

是什么

React基于浏览器的事件机制自身实现了一套事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等,在React中这套事件机制被称之为合成事件;

合成事件是 React模拟原生 DOM事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器

执行顺序

  • React 所有事件都挂载在 document 对象上

  • 当真实 DOM 元素触发事件,会冒泡到 document 对象后,再处理 React 事件

  • 所以会先执行原生事件,然后处理 React 事件

  • 最后真正执行 document 上挂载的事件

总结

  • React 上注册的事件最终会绑定在document这个 DOM 上,而不是 React 组件对应的 DOM(减少内存开销就是因为所有的事件都绑定在 document 上,其他节点没有绑定事件)

  • React 自身实现了一套事件冒泡机制,所以这也就是为什么我们 event.stopPropagation()无效的原因。

  • React 通过队列的形式,从触发的组件向父组件回溯,然后调用他们 JSX 中定义的 callback

  • React 有一套自己的合成事件 SyntheticEvent

了解更多详情请点击React事件机制的理解

React事件绑定的方式有哪些?区别?

==================================================================================

  • render方法中使用bind

  • render方法中使用箭头函数

  • constructor中bind

  • 定义阶段使用箭头函数绑定

class App extends React.Component {

handleClick() {

console.log('this > ', this);

}

render() {

return (

{/1.render方法中使用bind/}

test

{/*2.render方法中使用箭头函数 */}

)

}

}

class App extends React.Component {

constructor(props) {

super(props);

//3.constructor中bind

this.handleClick = this.handleClick.bind(this);

}

handleClick() {

console.log('this > ', this);

}

render() {

return (

test

)

}

}

class App extends React.Component {

//4.定义阶段使用箭头函数绑定

handleClick = () => {

console.log('this > ', this);

}

render() {

return (

test

)

}

}

区别

  • 编写方面:方式一、方式二写法简单,方式三的编写过于冗杂

  • 性能方面:方式一和方式二在每次组件render的时候都会生成新的方法实例,性能问题欠缺。若该函数作为属性值传给子组件的时候,都会导致额外的渲染。而方式三、方式四只会生成一个方法实例

  • 综合上述,方式四(箭头函数绑定)是最优的事件绑定方式

React组件生命周期有几个阶段

===============================================================================

  1. 初始渲染阶段这是组件即将开始其生命之旅并进入 DOM 的阶段。

getDefaultProps:获取实例的默认属性

getInitialState:获取每个实例的初始化状态

componentWillMount:组件即将被装载、渲染到页面上

render:组件在这里生成虚拟的 DOM 节点

componentDidMount:组件真正在被装载之后

  1. 更新阶段一旦组件被添加到 DOM,它只有在 prop 或状态发生变化时才可能更新和重新渲染。这些只发生在这个阶段。

componentWillReceiveProps:组件将要接收到属性的时候调用

shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)

componentWillUpdate:组件即将更新不能修改属性和状态

render:组件重新描绘

componentDidUpdate:组件已经更新

  1. 卸载阶段这是组件生命周期的最后阶段,组件被销毁并从 DOM 中删除。

componentWillUnmount:组件即将销毁

详细解释 React 组件的生命周期方法

===================================================================================

  1. componentWillMount() – 在渲染之前执行,在客户端和服务器端都会执行。

  2. componentDidMount() – 仅在第一次渲染后在客户端执行。

  3. componentWillReceiveProps() – 当从父类接收到 props 并且在调用另一个渲染器之前调用。

  4. shouldComponentUpdate() – 根据特定条件返回 true 或 false。如果你希望更新组件,请返回true ,不想更新组件则返回 false就会阻止render渲染。默认情况下,它返回 true。

  5. componentWillUpdate() – 在 DOM 中进行渲染之前调用。

  6. componentDidUpdate() – 在渲染发生后立即调用。

总结:

  • 函数式编程其实是一种编程思想,它追求更细的粒度,将应用拆分成一组组极小的单元函数,组合调用操作数据流;

  • 它提倡着 纯函数 / 函数复合 / 数据不可变, 谨慎对待函数内的 状态共享 / 依赖外部 / 副作用;

Tips:

其实我们很难也不需要在面试过程中去完美地阐述出整套思想,这里也只是浅尝辄止,一些个人理解而已。博主也是初级小菜鸟,停留在表面而已,只求对大家能有所帮助,轻喷🤣;

我个人觉得: 这些编程范式之间,其实并不矛盾,各有各的 优劣势

理解和学习它们的理念与优势,合理地 设计融合,将优秀的软件编程思想用于提升我们应用;

所有设计思想,最终的目标一定是使我们的应用更加 解耦颗粒化、易拓展、易测试、高复用,开发更为高效和安全

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值