前端面试 —— React篇

  在准备前端面试的过程中,发现前端的知识体系涉及的内容很广很多,在网上搜罗整理了一些前端面试的问题及答案,一方面是为了面试,另一方面是对很多基础和常用知识的复习。本篇是React篇
  传送门:
  前端面试 —— JavaScript基础篇

问题汇总

React生命周期函数?

  生命周期函数指在某一个时刻组件会自动调用执行的函数
  componentWillMount() -> 组件即将被挂载(第一次)到页面的时刻自动执行
  render() -> state/props改变时会自动调用,渲染页面
  componentDidMount() -> 组件被挂载(第一次)到页面之后自动执行
  componentWillReceiveProps()[props] -> 1. 一个组件从父组件接收了参数;2. 如果这个组件第一次存在于父组件中,不会执行;如果这个组件之前已经存在于父组件中,才会执行
  shouldComponentUpdate() -> 组件更新之前自动执行,返回布尔值决定组件是否更新
  componentWillUpdate() -> 组建更新之前,shouldComponentUpdate()返回true之后,自动执行
  componentDidUpdate() -> 组建更新完成之后自动执行
  componentWillUnmount() -> 当组件即将被从页面中剔除的时候自动执行
  getDerivedStateFromProps() -> React新的生命周期函数,父组件传递给子组件的props发生变化的时候,就会执行,然后更新state,为了替代即将被废除的componentWillReceiveProps()这个生命周期函数
  getSnapshotBeforeUpdate() -> React新的生命周期函数,当组件发生更新之前,组件会获取到DOM上的信息,传递给componentDidUpdate()作为最后一个参数。如果在组件更新时,想获取到更新前的页面DOM结构时候,可以使用
  1. Initialization(初始化): setup state and props (constructor())
  2. Mounting(挂载): componentWillMount() -> render() -> componentDidMount()
  3. Updation(更新: state/props改变):
   componentWillReceiveProps()[props] -> shouldComponentUpdate() ->
   | true: componentWillUpdate() -> render() -> componentDidUpdate()
   | false: x
  4. Unmounting(组件去除): componentWillUnmount()

redux中间件(thunk、saga、…)的原理是什么?

  redux流程是派发action,action传给store,store转给reducer,reducer再修改store
中间件位于派发action和action到store之间,也就是action和store之间。action和store之间沟通的桥梁是dispatcher,如果单纯调用store.dispatch(action),直接将action传递给store,此时action只能是一个对象;而redux-thunk的引入使得这个action可以是一个函数。
  具体原理:action到达store之前,会经过中间件,中间件会将函数式action转换成一个对象再传递给store。根据源码,我们可以看出如果传入的action是函数,则返回这个函数的调用,如果本身传入的函数是异步函数,我们完全可以在函数调用结束后,获取数据再次触发dispatch实现异步效果。

你会把数据统一放到redux中管理,还是共享数据放在redux中管理?

  1. 共享数据放在redux中管理,有一个明显的缺点,就是对于业务复杂的项目来说,可维护性差:因为对于一个组件来说,有可能既有state存储数据,又有props存储数据,还有redux存储数据,一旦出现问题,很难进行定位;所有数据统一redux管理,数据管理方式是相同的,问题定位方便
  2. 项目的可扩展性,可能某一组件的state数据在未来成为了共享数据,此时再进行数据的迁徙,不如最开始直接统一管理
  3. 附加:immutable + react-redux 可以提高项目性能

componentWillReceiveProps()的调用时机?

  1. 子组件从父组件接收了参数
  2. 如果子组件第一次存在于父组件中,不会执行;如果子组件之前已经存在于父组件中,才会执行

React性能优化的实践例子?

  PureComponent - 已经实现了shouldComponentUpdate()这个生命周期函数 [+ immutable.js 库]

虚拟DOM是什么?为什么虚拟DOM会提升代码性能?

  真实DOM节点的一个JS对象;不采用虚拟DOM时,如果想要比较页面差异,需要进行真实DOM节点比较,而DOM节点会绑定事件、有属性、各种方法,做比较耗性能;而单纯比较JS对象比较快,所以虚拟DOM的出现提升了react性能。

webpack中,是借助loader完成的JSX代码的转化,还是babel?

  babel-preset-react完成react代码转化成ES5,Vue是借助于webpack的vue-loader

调用setState后,发生了什么?

  setState是一个异步过程,它会集齐一批需要更新的组件然后一起更新

setState是异步的,这个点你什么时候遇到过坑?

  推荐使用函数式调用,例:

1
2
3
4
this.setState((prevState) => ({
age: prevState.age + 1
}), () => {}
); // 在第二个回调函数中可以得到更新的age值

  1. setState异步的,是会将短时间内的所有setState合并然后进行改变,如果用对象式调用,可能会出现阶跃式变化。
  2. 因为是异步,所以在第二个回调函数中可以保证得到已经更新的值

refs的作用是什么?你在什么业务场景下使用过refs?

  操作DOM -> 渲染了一个图片,展示完图片后,获取宽高(放大镜🔍功能)

ref采用函数式写法的好处?

  获取DOM元素,切记ref使用函数式写法,例:

1
2
3
4
render() {
return <div ref={(div) => { this.elem = div }}></div>
// elem名字任意,现在我们可以通过this.elem访问该div标签
}

  函数式写法好处在,方便react销毁组件/重新渲染时,有效清空ref引用里的内容,防止内存泄漏

高阶组件你是怎么理解的,它本质是一个什么东西?

  设计模式中有一个说法:组合优于继承。
  高阶组件(函数)接收参数,返回函数;高阶组件是对组件进行包装,然后返回一个新的组件。通常情况下,当一个组件会被很多组件调用,但是其中有些部分需要动态改变,我们就可以把公用的部分写入高阶组件,然后通过向高阶组件传递额外参数来进行动态改变。
  Hooks的出现解决了高阶组件地狱的问题。

受控组件和非受控组件的区别?

  受控组件的改变完全受控于数据的变化;非受控组件通过refs获取DOM节点上的内容进行操作。
  受控组件更好:react是一个数据驱动的框架,是一个反馈与相应式的框架。

函数组件和Hooks?

  Hooks的引入使得函数组件可以使用state,常见的一些API有useState(), useEffect(), useMemo(), useCallback(), useContext(), …

函数组件怎么做性能优化?

  函数组件相比类组件好在:由于是函数,没有生命周期,没有构造类的过程;但是,只要props改变,就会导致函数组件重新渲染。因此,可以使用React中的memo()对函数组件进行包装,包装后的组件就带有了shouldComponentUpdate()的特性,因此可以提升性能。

哪个生命周期里发送ajax请求?

  推荐在componentDidMount()
  为什么不推荐componentWillMount()?
  1. componentWillMount()在新版本react中已经被废弃了
  2. 做SSR(服务器端渲染)时,componentWillMount()要做服务器端数据的获取,不能被占用

SSR的原理是什么?

  因为虚拟DOM的引入,我们可以在服务器端对DOM的JS对象进行操作渲染,运行react的代码

React, jquery, vue是否可以共存在一个项目中?

  是可以共存的,怎么共存?例:

1
2
3
4
5
6
7
...
<body>
<div><div>
<div id=‘react’></div>
<div id=‘vue’></div>
</body>
...

  jquery接管第一个div,只操作第一个div下的DOM
  react接管第二个div,只操作第二个div下的DOM
  vue接管第三个div,只操作第三个div下的DOM

如何避免ajax数据重新获取?

  可以在react-redux中进行状态管理,比如可以用一个共享数据getData来表示是否已经获取过数据,true即获取过,则不需要再次请求获取数据;反之进行ajax请求获取数据。

react-router4的核心思想是什么?和3有什么区别?

  4 - 路由成为了组件,使用灵活,例如:, ,组件式路由思想
  3 - 基于配置的路由思想

react-router的基本原理, hashHistory和browserHistory?

  hashHistory - 路由不需要后端支持,上线可以直接使用
  browserHistory - URL形式漂亮,用户体验好,但是必须在后端Apache/Nginx服务器做相应路由配置

组件是什么?类是什么?类被编译成什么?

  模块的概念,存在于webpack一类的打包工具里,组件不是模块!!!组件指的是页面的一部分,本质上就是一个类,类是带有数据和功能的集合,ES6的类对应(编译后)ES5的构造函数。

reselect是做什么使用的?

  如果依赖的数据没有发生变化,计算属性就不会重新计算(做了缓存,提升代码性能)

什么情况下使用异步组件(reloadable库)?

  进入首页,只引入首页的代码,单独首页的包;同理,详情页面、后台每个页单独一个包。访问哪个页面,再加载这个页面对应的JS文件,这样可以把一个容量大的项目拆分成数个小包(异步组件)

xss攻击在react中如何防范?

  首先react本身已经做好了xss攻击防护,但是有:

1
dangerouslySetInnerHTML={{__html: ‘<script>alert(1)</script>’}}

  此时就容易被攻击,所以要慎用dangerouslySetInnerHTML

你是如何跟着社区成长的?

  根据自身成长经历开放性回答

文章引用和推荐

  1. 必须要会的50个React面试题 来自前端先锋的掘金
------------------------ The End ------------------------

本文标题:前端面试 —— React篇

文章作者:Lu, Ruihui

发布时间:2020年08月03日 - 19:36:21

最后更新:2021年04月13日 - 19:08:02

原始链接:https://github.com/cs-lurh0826/cs-lurh0826.github.io/Interview-Questions/frontend-interview-react/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

一花一世界,一叶一追寻