React 介绍
它是一个用于构建用户界面的JavaScript库,通过组件化的方式解决视图层开发复用的问题,本质是一个组件化框架。
声明式、组件化、通用性(一次学习,随处编写)
- 声明式?
- 组件化?
- 通用性?
为什么React要用JSX
JSX 是一个 JavaScript 的语法扩展,或者说是一个类似于 XML 的 ECMAScript 语法扩展,代码更简洁,可读性更强
JSX 主要用于声明 React 元素,但 React 中并不强制使用 JSX。即使使用了 JSX,也会在构建过程中,通过 Babel 插件编译为 React.createElement。所以 JSX 更像是 React.createElement 的一种语法糖。
如何避免生命周期中的坑
只有React类组件有生命周期,函数式组件并没有生命周期的概念,因为它本身是一个函数,只会从头执行到尾。
1,constructor
被去除
- constructor 中并不推荐去处理初始化以外的逻辑;
- 本身 constructor 并不属于 React 的生命周期,它只是 Class 的初始化函数;
- 通过移除 constructor,代码也会变得更为简洁。
2,在 componentDidMount
中发起网络请求
- 如果在UNSAFE_componentWillMount中发起请求,由于React的异步渲染机制,该方法可能会被多次调用。
- 页面渲染完毕后再调用接口,避免了因为错误请求导致的页面渲染不出来的问题,影响用户体验感
3,shouldComponentUpdate
常用于性能优化
-
通过添加判断条件来阻止不必要的渲染
-
PureComponent
是React官方提供的通用的优化方案PureComponent 的核心原理就是默认实现了shouldComponentUpdate函数,在这个函数中对 props 和 state 进行浅比较,用来判断是否触发更新。
4,componentWillUnmount
主要用于执行清理工作
一个比较常见的 Bug 就是忘记在 componentWillUnmount 中取消定时器,导致定时操作依然在组件销毁后不停地执行。所以一定要在该阶段解除事件绑定,取消定时器。
5,render
执行渲染
- render函数应该是一个纯函数,不应该在里面产生副作用,比如调用setState或者绑定事件
- 为什么不能 setState 呢?因为 render 函数在每次渲染时都会被调用,而 setState 会触发渲染,就会造成死循环。
- 为什么不能绑定事件呢?因为容易被频繁调用注册。
渲染
-
函数组件任何情况下都会重新渲染,它并没有生命周期,但官方提供了一种优化手段,那就是React.memo.
const MyComponent = React.memo(function MyComponent(props) { /* 使用 props 渲染 */ });
React.memo 并不是阻断渲染,而是跳过渲染组件的操作并直接复用最近一次渲染的结果,这与 shouldComponentUpdate 是完全不同的。
-
React.Component
如果不实现
shouldComponentUpdate
函数,那么有两种情况触发重新渲染。- 当 state 发生变化时。这个很好理解,是常见的情况。
- 当父级组件的 Props 传入时。无论 Props 有没有变化,只要传入就会引发重新渲染。
-
React.PureComponent
PureComponent
默认实现了shouldComponentUpdate
函数。所以仅在props
与state
进行浅比较后,确认有变更时才会触发重新渲染。
类组件与函数组件的区别:
相同点
- 组件是React可复用的最小代码片段,无论是函数组件还是类组件,在使用方式和最终呈现效果上是一样的
不同点
-
设计思想不同。类组件是面向对象编程,所以有继承,有属性,有内部状态的管理;函数组件是函数式编程,主打的是 immutable、没有副作用、引用透明等特点,输入与输出存在某种特定的映射关系,输入一定的情况下,输出必然是一定的。
相较于类组件,函数组件更纯粹、简单、易测试 (本质上最大的区别)
-
类组件有生命周期,函数组件没有生命周期,可通过高阶组件包裹函数来模拟生命周期,但现在有了hooks,这一点区别也就不存在了
-
设计模式,类组件可继承,函数组件不可继承。但React中不推荐继承已有的组件,因为灵活性很差
组合优于继承
-
性能优化:类组件通过
shouldComponentUpdate
函数阻断渲染,函数组件通过React.memo
来优化。React.memo 不是阻断渲染而是直接跳过渲染,采用上一次的渲染结果。
类组件不及函数组件的原因:
-
this的模糊性;
-
业务逻辑散落在生命周期中;
-
React 的组件代码缺乏标准的拆分方式
-
hooks的函数组件可以提供比原先更细粒度的逻辑组织与复用,
针对同一个功能的代码整合度更高,复用性更强
如何设计React组件?
展示组件的复用性更强,状态组件则更专注于业务本身。
针对高阶组件,refs属性不能透传,可通过 React.forwardRef
解决