React.Component
1-如果将组件定义为ES6的class类,就必须继承这个React.Component。
2-React.Componet这个基础类中必须要有render(){}这个函数。
3-注意这句话:我们强烈建议你不要创建自己的组件基类。 在 React 组件中,代码重用的主要方式是组合而不是继承。
4-对于第三点,我们可以具体看
- 包含关系:{props.children}本质就是对象,将他们当作props一样传递,回一下Vue中的slot概念,但在 React 中没有“槽”这一概念的限制,你可以将任何东西作为 props进行传递。
- vue slot
- 特殊关系:{props.title}、{props.head}等组合起来
- 组合:props和组合为我们提供了清晰并且安全的制定复用组件的灵活方式,组件可以接受任意props,包括基本数据类型(String,Null等)、React元素(Object对象)、函数等
- 继承:如果你想要在组件间复用非 UI 的功能,我们建议将其提取为一个单独的 JavaScript 模块,如函数、对象或者类。组件可以直接引入(import)而无需通过(extend) 继承它们,比如我们经常使用的tool.js、util.js等文件中的公用方法
5-React.Component会注入React的
- 挂载时:construction和componentDidMount只有在挂载的时候触发一次,那么两者在父子组件中的渲染情况又是怎样的呢?下图显示可知construction和componentDidMount渲染情况是不一样的

- 更新时:又可以分为多种情况(父组件只更新state数据,父组件更新子组件的props数据,子组件更新state,父组件强制使用forceUpdate方法 - 隐含shouldComponentUpdate生命周期方法)

- 卸载时:谁卸载,谁会调用componentWillUnmount,和componentDidMount不一样。
- 错误处理时:componentDidCatch
render
1-render返回什么内容
-
React元素,
<div>,<MyComponent>html元素和自定义元素 -
数组或者fragments
<React.Fragment> <!--在真正渲染的时候Fragment不会被渲染成div或者另外元素--> <ChildA /> <ChildB /> <ChildC /> </React.Fragment> -
Portals
Portals = ReactDOM.createPortal(child, container) // child加载到container下面 modalRoot.appendChild(container) // container挂载到modal根节点下面
Portals在A组件中声明,实际挂载到body下面到div中,那么Portals中到click事件冒泡会在A中出现还是body中出现?
-
字符串或数值类型
-
布尔类型或 null
2-render中保持纯函数,而不要有与浏览器的交互,这些交互可以放在componentDidMount中
constructor(props)
1-是否要写构造函数,如果不需要设定state和绑定函数,那么不需要主动声明构造方法
2-在构造函数中只做两件事,设定初始state和绑定函数,对于有副作用和订阅关系的时候,放在componentDidMount中
3-千万不要将props直接赋值给state,因为你直接可以用this.props获取,这里带来的问题是,如果你更改了this.props中值,react并不会动态修改state的值,导致state的值和props的值不一致
4-一定要使用this.state.email = this.props.defaultEmail,那么父组件在子组件上绑定唯一的key,促使父组件修改props中email时,绑定在子组件上的key也修改了,迫使子组件render,从而重新获取this.props.defaultEmain的值
componentDidMount
1-请求网络数据的好地方
2-在这个地方设置了订阅,那么在componentWillUnmount一定要取消订阅
3-如果在componentDidMount中setState,重新更新state的值的时候,它将触发额外渲染,但此渲染会发生在浏览器更新屏幕之前。如此保证了即使在 render() 两次调用的情况下,用户也不会看到中间状态。(但是有性能问题)(这样也为什么说是请求网络数据的好地方了
componentDidUpdate(prevProps, prevState, snapshot)
1-在这里面如果setState,一定要有一个if语句,进行条件限制,否则一但更新就会render,产生一些性能问题
2-snapShot参数是,getSnapshotBeforeUpdate生命周期函数的返回值,否则为undefined
3-首次渲染不会执行此方法,更新的时候执行这个方法
componentWillUnmount()
1-取消订阅,取消timer,取消请求等等,一系列清除工作
不常用的生命周期函数
shouldComponentUpdate
1-返回Boolean,true则render或者componentDidUpdate,反之false就不渲染
2-首次渲染或者forceUpdate的时候,组件本身的shouldComponentUpdate不执行
static getDerivedStateFromProps(props, state)
作用:会在调用 render方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
getSnapshotBeforeUpdate
作用:snapshot 翻译就是快照,就是在更新前获取DOM元素的信息的,比如滚动条位置,比如DOM的位置,以便与componentDidUpdate,具体更新挂载DOM元素的时候,能够获取到这部分的参数
Error boundaries(错误界限)
1-static getDerivedStateFromError() 或 componentDidCatch()
2-用来展示降级UI,而不是页面崩溃
3-不要用来控制流程
setState((state, props) => stateChange, [callback])
1-setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。
2-将 setState() 视为请求而不是立即更新组件的命令
3-后调用的 setState() 将覆盖同一周期内先调用 setState 的值,因此商品数仅增加一次。如果后续状态取决于当前状态,我们建议使用 updater 函数的形式代替:
先:this.setState({quantity: quantity + 1})
后:this.setState({quantity: quantity + 1})
变成
Object.assign(
previousState,
{quantity: state.quantity + 1},
{quantity: state.quantity + 1},
...
)