在准备前端面试的过程中,发现前端的知识体系涉及的内容很广很多,在网上搜罗整理了一些前端面试的问题及答案,一方面是为了面试,另一方面是对很多基础和常用知识的复习。本篇是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
4this.setState((prevState) => ({
age: prevState.age + 1
}), () => {}
); // 在第二个回调函数中可以得到更新的age值
1. setState异步的,是会将短时间内的所有setState合并然后进行改变,如果用对象式调用,可能会出现阶跃式变化。
2. 因为是异步,所以在第二个回调函数中可以保证得到已经更新的值
refs的作用是什么?你在什么业务场景下使用过refs?
操作DOM -> 渲染了一个图片,展示完图片后,获取宽高(放大镜🔍功能)
ref采用函数式写法的好处?
获取DOM元素,切记ref使用函数式写法,例:1
2
3
4render() {
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
你是如何跟着社区成长的?
根据自身成长经历开放性回答
文章引用和推荐
- 必须要会的50个React面试题 来自前端先锋的掘金