Appearance
使用 React 过程中遇到的问题
react 有什么特性
主要特性分为:
- JSX 语法
- 单向数据绑定
- 虚拟 DOM
- 声明式编程
- Component
借助这些特性,react 整体使用起来更加简单高效,组件式开发提高了代码的复用率
生命周期有哪些不同阶段?每个阶段对应的方法是?
- 新版生命周期整体流程如下:

- 旧版生命周期整体流程如下:

state 和 props 有什么区别
两者相同点:
- 两者都是 JavaScript 对象
- 两者都是用于保存信息
- 都能触发渲染更新
区别:
- props 是外部传递给组件的,而 state 是在组件内部自己管理的,一般在 constructor 中初始化
- props 在组件内部是不可修改的,但是 state 在组件内部可以进行修改
- state 是多变的、可以修改
super()和 super(props)有什么区别
在 React 中,类组件基于 ES6,所以在 constructor 中必须使用 super
在调用 super 过程,无论是否传入 props,React 内部都会将 porps 赋值给组件实例 porps 属性中
如果只调用了 super(),那么 this.props 在 super()和构造函数结束之间仍是 undefined
setState 执行机制
在 react 类组件的状态需要通过 setState 进行更改,在不同的场景下对应不同的执行顺序:
- 在组件生命周期或者 React 合成事件中,setState 是异步的
- 在 setTimeout 或者原生 dom 事件中,setState 是同步的
当我们批量更改 state 的值的时候,react 内部会将其进行覆盖,只取最后一次的执行结果
当需要下一个 state 依赖当前 state 的时候,则可以在 setState 中传递一个回调函数进行下次更新
React 的事件机制
React 基于浏览器的事件机制自身实现了一套事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等
组件注册的事件最终会绑定在 document 这个 DOM 上,而不是 React 组件对应的 DOM,从而节省内存开销
自身实现了一套事件冒泡机制,阻止不同时间段的冒泡行为,需要对应使用不同的方法
时间绑定的方式有哪些
react 常见的绑定方式如下:
- render 方法中使用 bind
- render 方法中使用箭头函数
- constructor 中 bind
- 定义阶段使用箭头函数绑定
前两种方式在每次组件 render 的时候都会生成新的方法实例,性能问题欠缺
构建组件的方式有哪些,有什么区别
组件的创建主要分成了三种方式:
- 函数式创建
- 继承 React.Component 创建
- 通过 React.createClass 方法创建
如今一般都是前两种方式,对于一些无状态的组件创建,建议使用函数式创建的方式,再比如 hooks 的机制下,函数式组件能做类组件对应的事情,所以建议都使用函数式的方式来创建组件
组件之间如何通信
组件间通信可以通过 props、传递回调函数、context、redux 等形式进行组件之间通讯
key 有什么作用
使用 key 是 react 性能优化的手段,在一系列数据最前面插入元素,如果没有 key 的值,则所有的元素都需要进行更换,而有 key 的情况只需要将最新元素插入到前面,不涉及删除操作,在使用 key 的时候应保证:
- key 应该是唯一的
- key 不要使用随机值(随机数在下一次 render 时,会重新生成一个数字)
- 避免使用 index 作为 key
refs 的理解和应用场景
refs 允许我们访问 DOM 节点或在 render 方法中创建的 React 元素
下面的场景使用 refs 非常有用:
- 对 Dom 元素的焦点控制、内容选择、控制
- 对 Dom 元素的内容设置及媒体播放
- 对 Dom 元素的操作和对组件实例的操作
- 集成第三方 DOM 库
Hooks 的理解,解决了什么问题
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性
解决问题如下:
- 难以重用和共享组件中的与状态相关的逻辑
- 逻辑复杂的组件难以开发与维护,当我们的组件需要处理多个互不相关的 local state 时,每个生命周期函数中可能会包含着各种互不相关的逻辑在里面
- 类组件中的 this 增加学习成本,类组件在基于现有工具的优化上存在些许问题
- 由于业务变动,函数组件不得不改为类组件等等
如何引入 css
常见的 CSS 引入方式如下:
- 在组件内直接使用
- 组件中引入.css 文件
- 组件中引入.module.css 文件
- CSS in JS
组件内直接使用 css 会导致大量的代码,而文件中直接引入 css 文件是全局作用域,发生层叠
引入.module.css 文件能够解决局部作用域问题,但是不方便动态修改样式,需要使用内联的方式进行样式的编写
css in js 这种方法,可以满足大部分场景的应用,可以类似于预处理器一样样式嵌套、定义、修改状态等
redux 工作原理
redux 要求我们把数据都放在 store 公共存储空间,一个组件改变了 store 里的数据内容,其他组件就能感知到 store 的变化,再来取数据,从而间接的实现了这些数据传递的功能
工作流程图如下:

redux 中间件有哪些
- redux-thunk:用于异步操作
- redux-logger:用于日志记录
react-router 组件有哪些
常见的组件有:
- BrowserRouter、HashRouter
- Route
- Link、NavLink
- switch
- redirect
render 触发时机
在 React 中,类组件只要执行了 setState 方法,就一定会触发 render 函数执行
函数组件 useState 会判断当前值有无发生改变确定是否执行 render 方法,一旦父组件发生渲染,子组件也会渲染
如何减少 render
父组件渲染导致子组件渲染,子组件并没有发生任何改变,这时候就可以从避免无谓的渲染,具体实现的方式有如下:
- shouldComponentUpdate
- PureComponent
- React.memo
JSX 转化 DOM 过程
jsx 首先会转化成 React.createElement 这种形式,React.createElement 作用是生成一个虚拟 Dom 对象,然后会通过 ReactDOM.render 进行渲染成真实 DOM
性能优化手段有哪些
除了减少 render 的渲染之外,还可以通过以下手段进行优化:
- 避免使用内联函数
- 使用 React Fragments 避免额外标记
- 使用 Immutable
- 懒加载组件
- 事件绑定方式
- 服务端渲染
如何做服务端渲染
node server 接收客户端请求,得到当前的请求 url 路径,然后在已有的路由表内查找到对应的组件,拿到需要请求的数据,将数据作为 props、context 或者 store 形式传入组件
然后基于 react 内置的服务端渲染方法 renderToString()把组件渲染为 html 字符串在把最终的 html 进行输出前需要将数据注入到浏览器端
浏览器开始进行渲染和节点对比,然后执行完成组件内事件绑定和一些交互,浏览器重用了服务端输出的 html 节点,整个流程结束
