以下是React学习基础,面试中也是常问的
点击我获取更多资源
1. React类组件中的setState是异步还是同步?
- 同步条件有
- 类组件:函数加上setTimeout, state修改后,state和dom都是新值
- 异步条件有
- 类组件:state修改后,state和dom都是旧值, 原因是setState会批量更新
- 函数组件:state修改后,state是旧值,但是dom是旧值,但是如果是在setTimeout中执行,只有dom是新值
- 补充
- 同步:在可控的地方,比如在react生命周期事件合成的事件中,都会走合并操作,延迟更新
- 异步:无法控制的地方,比如原生事件,具体就是addEventListener, setTimeout,setInterval事件等
- setState第二个参数作用
- 可选的回调,可以拿到更新后的数据
2. React实现缓存方式有哪些,他们区别?
- 类组件
- PureComponent(对props进行浅拷贝), React.memo(可以执行参数)
- 函数组件
- userCallback, 缓存函数引用
- useMemo, 缓存计算数据的值
3. React事件机制
- React是合成事件,指react用js模拟dom事件
- react并不是将click事件绑定到真实的dom上,而是在document处监听所有支持的事件,当事件冒泡至document时,react将事件内容封装并提交由真实处理函数处理
- 合成事件处理原因
- 统一解决跨浏览器兼容问题
- 避免dom事件滥用
4. React-Fiber的理解,解决了哪些问题
- React Fiber 是React的新的分层渲染引擎,它将渲染过程分层,然后通过多线程进行渲染,以提高性能
- 给浏览器喘息机会,让是cpu执行权,等浏览器空闲再去执行渲染
5. 哪些方法会触发react重新渲染
- setState, 会触发render
- 父组件重新渲染,会导致子组件重新渲染
- 重新渲染render会做什么
- 会对新旧的VNode进行对比,diff算法
- 对新旧两棵树进行一次深度优先遍历,并标记每一个节点,在深度遍历时候,对遍历到的每一个节点进行比较,如果由差异,放在一个对象里面
- 遍历差异对象,根据差异类型,根据对应规则个更新VNode
5. React声明组件有哪些方式?有什么不同
- 函数式定义, 不能访问this对象,没有生命周期
- ES5原生方式 React.createClass, 会绑定函数方法,导致性能开销
- ES6方式 extends React.Component, 不会绑定函数方法,性能会好一些
6. 对有组件和无组件理解和使用场景
- 有组件:特点
- 是类组件
- 有继承
- 有this
- 有生命周期
- 内部使用state,维护自身变化, 根据外部传入props和自身的state,重新渲染
- 无组件:特点
- 不依赖自身状态state
- 可以是类组件或则函数组件
- 没有this
- 性能更高
- 内部不维护state,根据外部传入props渲染,props变化,重新渲染
6. Fragment 理解
- Fragment是React 16.0后新增的,用于将多个子元素合并为一个元素,减少dom节点数量,减少性能开销
import React, { Component, Fragment } from 'react'
// 一般形式
render() {
return (
<React.Fragment>
<ChildA />
<ChildB />
<ChildC />
</React.Fragment>
);
}
// 也可以写成以下形式
render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}
7. React 获取 dom元素方法
- 字符串格式:
- 函数格式: <p ref={ele => this.info = ele} />
- createRef方法: React16提供的api
8. createPortal
- 用于将组件渲染到指定的dom节点中,一般用于弹窗,消息框,弹窗,消息框等
import { useState,useEffect } from "react";
import {createPortal} from "react-dom";
const Protal = (props) => {
return (
props.visable && (
<div>protal...</div>
)
)
}
const App = ()=> {
const [visable, setVisable] = useState(false)
return (
<div>
{
createPortal(<Protal visable={visable} />, document.getElementById('dom'))
}
<button onClick={()=>setVisable(true)}>show protal</button>
</div>
)
}
export default App;
9. 如何避免不必要的render
- 使用shouldComponentUpdate方法,返回false,阻止组件重新渲染
- 使用PureComponent,PureComponent是React的基类,它实现了shouldComponentUpdate方法,返回false,阻止组件重新渲染
- 使用memo缓存组件,memo是React的基类,它实现了shouldComponentUpdate方法,返回false,阻止组件重新渲染
10. React context理解
- 提供了组件之间共享值得方式
- context不太推荐实用
10. React 受控组件和非受控组件
- 受控组件: 组件内部有state, 有this.state, 有this.setState, 有this.forceUpdate
- 非受控组件: 组件内部没有state, 有this.props, 有this.forceUpdate
11. React setState 调用原理
- 调用setState, 相当于分发器,根据参数不同,被派发到不同的功能函数中
- enqueueSetState,将state存放到状态队列中,并调用enqueueUpdate处理将要更新的对象
- enqueueUpdate中,判断对象是否isBatchingUpdates,是的花,走更新流程,否则轮询
12. setState 和 replaceState 的区别
- setState是修改部分状态,相当于Object.assign
- replaceStates是完全替换原来的状态
13. props 和 state 区别
- props是父传子, state是组件内状态
- props不能被修改,state可以修改
14. 生命周期
- 装载阶段(Mount), 第一次渲染,只发生一次
- constructor, 初始化state,给事件绑定this
- getDerivedStateFromProps, 从父组件获取props, 通过props更新state
- render, 返回需要渲染的内容
- componentDidMount, 组件装载后立即调用, 一般执行网络请求,添加订阅,执行依赖dom的操作
- 更新阶段(Update)
- getDerivedStateFromProps,父组件更新了props
- shouldComponentUpdate, 可以阻止组件重新渲染(返回false),提升速度,可以比较props和nextProps,state和nextState是否有变化(防止父类渲染,子类也重新渲染)
- getSnapshotBeofreUpdate,render执行后,componentDidUpdate,执行之前会触发该函数,主要最用是给componentDidUpdate准备数据
- componentDidUpdate, 更新组件后立即调用,首次渲染不会被调用,可以比较prop是否变化,取决是否要重新网络请求
- 卸载阶段(Unmount)
- componentWillUnmount, 可以清除定时器,取消订阅
- 错误处理阶段
- componentDidCatch
- 总结
- constructor,render,componentDidMount, componentDidUpdate, componentWillUnmount
15. react16.x, props改变后,在哪个生命周期中处理
- getDerivedStateFromProps,静态函数
static getDerivedStateFromProps(nextProps, prevState) {
const {type} = nextProps;
// 当传入的type发生变化的时候,更新state
if (type !== prevState.type) {
return {
type,
};
}
// 否则,对于state不进行任何操作
return null;
}
16. state, props触发更新的生命周期分别有什么区别
- shouldComponentUpdate,比较state, props是否发生变化,来决定是否执行getSnapshotBeforeUpdate
- getSnapshotBeforeUpdate(之前是componentWillUpdate),收集dom更新前的信息
- componentDidUpdate
17. 网络请求在哪个生命周期
- 最好放在componentDidMount
18. 组件通信方式
- 父-子,props方式
- 子-父, 函数回调
- 跨级,上下级组件通信,context
- 非嵌套组件通信, 自定义发布订阅模式,redux全局状态管理