react 面试题 高级_React面试题分享

整理了在react前端面试中,常会问到的东西,不仅限于react,还包括前端常用的基础

1.关于react框架

谈React框架,我们可以从框架出现的原因开始聊。在框架之前,我们使用原生的js去开发,前端的性能极大的受到频繁的dom操作的影响,其次,前端开发没有很好的代码开发规范,代码混乱,不利于开发、迭代

1.dom节点自身拥有大量的自身属性(我们常用的仅一小部分),每一次的dom操作,都需要重新挂载数量庞大的dom属性(这是频繁操作dom卡顿的一大原因)

2.从浏览器的渲染流程说起,浏览器在接受到html与css文件后,会根据html生成dom树,根据css生成一个对应的CSSOM树,然后将两棵树进行合并形成一个渲染的render树,接着计算每个dom节点的视觉上的大小与位置,最后将页面渲染到网页上,这是浏览器首次渲染的一个大概流程。

在用户操作过程中也会使得渲染中的某些流程再次触发,我们称之为回流或重绘,回流是由于我们的某些js操作使得dom结构、dom几何属性的更改,会重新计算生成render树,计算元素的位置、大小,最后重新渲染,这个过程是很耗性能的,所以频繁的dom操作会造成网页的卡顿,所以在之前,我们常会用文档碎片的方式批量更新dom。

react框架使用了虚拟dom很好的解决频繁操作dom的性能问题,react用js简单的模拟了dom树,我们在不再直接操作dom,而是操作虚拟dom,通过diff算法计算出前后虚拟dom的不同,再将不同点映射到真实dom上,极大的减少了dom结构的变化次数。

更重要的是react组件化的开发模式,在框架的组件化开发模式流行前,前端使用amd与cmd等模块化的方式来对项目进行模块化拆分、开发与管理,这种方式只是对js代码进行了一个分割,解决了命名冲突、变量泛滥与js加载顺序的问题,开发上并没有很大的变化,组件化的开发模式却是颠覆了前端的开发,组件化相对于之前的模块化进行了更为细化的整合,组件拥有自己的生命周期,有自己的数据状态管理,拥有自己的UI模板(JSX),我们能够很好的把控在组件的加载、更新与卸载过程中的变化。

2.React面试中常问到的点:

1.组件间传值:父与子之间的传递,通过props,父传子直接将数据通过props传递给子组件,子传父,依然利用父组件传递一个函数留以payload入口,传递给子组件触发;跨组件的传递,可以利用状态提升,也是利用props,跨多层次的传递就会显得很麻烦;context传递,不必利用组件树显示的逐层传递;利用第三方状态管理器redux、mobox等

2.如何在父组件中触发子组件实例中的方法:利用refs获取组件实例直接调用即可

3.redux是如何与react进行关联的:两个关键点,Provider与connect,Provider容器将根组件进行包裹将store注入,在Provider组件中通过props拿到store,将其注册到全局的context中,在需要使用到redux中的状态的组件里利用connect高阶组件,拿到Provider注入到context中的store,将store中需要的state和相关的dispatch方法直接map到需要使用的组件的props中,在组件中就可以利用props拿到redux的state与修改其的方法

4.redux:

独立的状态树,通过各子renducer合并后产生store,通过各子reducer将管理的state数据模块化,且各reducer中定义了改变当前state数据的处理函数,store通过dispatch相应的action(纯对象,包含type和payload数据)来改变相应的state数据

使用redux的好处:解决跨多层的非父子组件间的数据通信的麻烦(否则就是使用状态提升,需通过两组件共同的父组件将数据向下传递)

核心概念:state、reducer、action、store、dispatch,要熟悉各字面量之间的联系与运作原理

4.异步的setState:react是数据驱动的,每个被管理的state数据的更改都会引起组件重新render,state状态数据不允许直接修改,只能通过其提供的setState方法来进行更改,该方法的执行是异步的,调用时不会立即修改state的值,会在一定时间内收集到所有通过setState修改的state,最后进行统一的修改,这也是react自身的一个性能优化,减少了组件更新时不必要的render

5.react的生命周期:react的生命周期在c16.0前后有所不同,但都分为创建、更新与卸载过程,具体函数不赘述,理解react的数据驱动和生命周期能够帮助我们开发中避免一些问题,比如为什么不建议在didupdate中去setState

6.react的性能优化,PrueComponent或shouldComponentUpdate,react中,在一个组件发生了重新render后,其所有的子组件都会发生重新render,即使传递给子组件的props没有发生变化,因此,我们可以通过shouComponentUpdate钩子函数来通过前后props的浅层对比来判断传入的参数是否发生了变化,可减少无用的render,PureComponent也是重写了shouldCompoentUpdate来进行的性能优化。

7.函数式组件与class类组件:函数式组件就是一个UI模板,接受特定格式的props参数,将props渲染进JSX模板中并返回出去,没有自身需要管理的状态与生命周期,像页面中某些模块只是起展示的作用,不涉及复杂的逻辑交互,函数式组件是很好的选择

8.hook:v16.8提出了hook,让我们可以用函数式的方式来编写拥有自身state状态与生命周期(个人感觉hooks中不能再算是生命周期,仅仅是再组件更新中起到监听数据变化做出相应操作的作用,类似于vue中的watch)的组件,关键api是useState与useEffect

9.为什么使用react框架开发?有什么好处?

9.1性能优化:首先我们得了解,浏览器的性能是有一定限定的,但js的运行速度很快。

9.1.1  虚拟dom:react使用虚拟dom来模拟最终要挂载的真实dom,虚拟dom上只存在几个关键的属性,该节点类型,该节点上我们挂载的属性,以及children,相比起真实dom上数量庞大的属性,虚拟dom更简洁但也能够描绘出dom的一个真实结构。因此,操作虚拟dom的速度是远快于操作真实的dom节点的(每次的dom操作还会引起回流与重 排,造成大量的性能消耗)

9.1.2  diff算法:每次虚拟dom的更改会产生一棵新的虚拟dom树,与之前旧的树进行对比,将所有变化的点整合到一起,将这些变化再通过dom操作进行更替。而新旧dom树之间的对比就是用diff算法,而且React只做同一层次节点的对比而不是深度遍历每一个节点。

9.1.3 react组件加载、更新中会触发哪些过程?

React是数据(state/props)驱动的,state的变化会触发render函数的重新执行,而render是生成虚拟dom的关键与基础。组件在第一次渲染后会执行一遍render形成第一 棵虚拟dom,后续组件中state/props的变化也会造成组件的重新渲染,而每一次的重新渲染都会触发新的虚拟dom树的产生与diff比较(这也是为什么react不允许用户自己改变state而是用setState方法去更新state),再将不同点patch到真实dom上去,实现页面的更新

9.2 组件化开发(提供了一种代码的开发组织规范)

目前三大主流框架Angular、Vue与React都是组件化开发的模式。

代码组织与规范的好坏直接影响着开发者的开发、迭代成本,代码组织混乱,各种变量、逻辑处理满天飞,且随着后续需求的复杂化,代码的迭代、维护成本会变得及其高甚至不能维护,如果代码移交给后来者,那对后来者来说将是灾难;相反代码组织规范,逻辑清晰,有较好的备注习惯,开发起来则事半功倍,对于后来接手者也能够较快的熟悉代码逻辑与结构。

3.    关于前端性能优化

关键还是减少http请求次数。

进行小图片的整合(目的也是减少http的请求次数);

函数节流/防抖(能手写最好),解决高频次触发的事件问题;

合并css样式表与js脚本;

利用node中间层进行前端请求的合并,将从后端的拿到数据进行整合再发送给前端,减少了前端请求的次数,还省去了前端整合数据的过程;

将静态资源托管到cdn上;

代码压缩;

懒加载/预加载;

路由懒加载(单页面应用解决首屏空白、加载慢的问题);

SPA单页面应用:目前最好的用户体验的方式,前端页面无刷新,前端路由利用router实现模块的替换不需要去后端重新请求页面

4.   关于开发中常遇到的问题与解决方案

1.跨域:跨域是因为浏览器的同源策略,只有同协议、同端口与同ip才能相互请求访问。

解决方法:日常开发利用webpack的proxy配置代理;

后端的CORS跨域;

jsonp也可以跨域,不过现在用的太少了,而且Jsonp只能适用于get请求

4.    前端开发的基础常识

1. ES5/6/7

let/const:没有变量提升,且let可形成块级作用域

箭头函数:其this指向在定义时就确定了指向当前实例,常可以解决在组件开发中函数的this指向不为当前组件实例问题

解构赋值

展开运算符

模板字符串

Promise/generator/async await

2. html5与css3新特性

3.  闭包与原型链:闭包常会用到,用数组数据map渲染元素,需要为每个元素绑定事件需要用到map的数据时,原型链能帮助理解js的类与继承方式

4.  缓存Cookie/Storage,cookie常用来携带用户信息,随着请求自动携带

5.  Js中的异步:事件、定时器、Promise、ajax

5.    面试中常问到的原理性东西

1.    BFC与IFC:不同元素(Block与Inline)的布局规则,不同属性的设置会形成不同的排列规则的元素

2.    浏览器渲染流程:domTree+cssStyle=>renderTree=>layout=>渲染出来

3.    回流与重绘:回流会造成renderTree的结构变化,要重新生成renderTree,计算元素的布局数据,重绘只是某些不影响元素布局的样式更改,回流造成的性能的代价比较高

4.    Js如何实现异步的:主线程与事件轮询(event loop),同步代码在主线程中先执行,异步事件会放入任务队列,当主线程执行完之后再去进行事件轮询,将待执行的异步回调放在主线程中去执行

5.   React中的key:用于同层结构的diff判断,key值相同的元素,不会重复创建

原文链接:https://www.jianshu.com/p/a1a1d544c643

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值