组件生命周期
react 谷歌调试插件: react developer tools
- 组件的生命周期
- react 版本的生命周期: 15 版本 16 版本 17 版本【主流】
- react 15.x.x 15 版本生命周期
- react 16.0.0 - 16.3.x 16 版本
- react 16.3.0 以上 17 版本
 
- 除 15 版本以外,生命周期分为四个阶段
- 挂载阶段
- 特点: 自动执行,执行一次
 
- 更新阶段
- 触发条件: 组件调用了 setState || forceUpdate
 
- 卸载阶段
- 错误处理阶段【 15 版本是没有的 】
 
 
挂载阶段
- constructor
- 通过 props 参数可以获得绑定在组件身上的数据
- 可以定义 state
- 可以为类中的普通函数绑定 this 指针
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 
 | constructor(props: P) {
 
 
 
 super(props);
 
 this.state = {
 name: "yyc",
 };
 
 this.handler = this.handler.bind(this);
 }
 
 | 
- static getDerivedStateFromProps(props,state) { return {} }
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | 
 static getDerivedStateFromProps(props: P, state: S) {
 console.log("getDerivedStateFromProps");
 
 return {
 money: props.money,
 };
 }
 
 | 
- render
- 解析 this.state & this.props
- 将 jsx 形式的虚拟 dom 转成对象形式的虚拟 dom
- render 中不允许使用 this.setState() 如何你使用了,就会栈溢出
 
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | render() {return (
 <div>
 <p> {this.state.name} </p> {/* 解析this.state */}
 <p> {this.props.money} </p> {/* 解析this.props */}
 <p ref={(el) => (this.p = el)}>asdds</p> {/* 渲染成对象形式的虚拟DOM */}
 </div>
 );
 }
 
 | 
- componentDidMount
- 组件挂载结束
- 虚拟 DOM -> 真实 DOM
- 获得到了真实 dom,可以做真实 DOM 操作
- 数据请求发送
- 第三方库实例化
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | componentDidMount() {
 
 this.p.style.background = "red";
 
 fetch("http://59.110.226.77:3000/api/category")
 .then((data) => data.json())
 .then((res) => {
 console.log("res", res);
 })
 .catch((error) => Promise.reject(error));
 }
 
 | 
更新阶段
- static getDerivedStateFromProps 作用同挂载阶段
| 12
 3
 4
 5
 6
 
 | static getDerivedStateFromProps(props: P, state: S) {
 
 console.log("gdsfp");
 return {};
 }
 
 | 
- shouldComponentUpdate 表示组件是否应该更新
- return true 表示组件更新
- return false 表示组件不更新
- 功能
- 渲染优化: 新属性 vs 旧属性 || 新状态 vs 旧状态
- 比较手动来写
 
 
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | shouldComponentUpdate(nextProps: P, nextState: S) {
 
 
 
 console.log("scu");
 return this.state.name !== nextState.name;
 }
 
 
 | 
- render 同挂载阶段
- getSnapShotBeforeUpdate 在更新前获取快照
| 12
 3
 4
 5
 6
 7
 
 | getSnapshotBeforeUpdate = (prevProps: P, prevState: S) => {console.log("gsbu");
 
 
 
 return 1000;
 };
 
 | 
- 它的返回值会传递给 componentDidUpdate 的第三个参数
- componentDidUpdate
- 将再次生成的虚拟 DOM 和就的虚拟 DOM,通过 filber 进行比较,生成 patch 补丁对象
- patch 补丁对象渲染为真实 DOM
- 发送数据请求
- 真实 dom 操作
- 可以获取 getSnapShotBeforeUpdate 传递过来的数据
 
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | componentDidUpdate(prevProps: P, prevState: S, snapShot: number) {
 
 
 
 
 
 console.log("我得到了", snapShot);
 }
 
 | 
PureComponent vs Component
在 component 中如果渲染一样的值,都会触发 render()钩子函数,导致性能浪费
- PureComponent 默认会进行一次新旧 state 或者新旧 props 的对比,可以得到一个性能优化的目的
- 缺点:
- 它只能对比一层数据,所以我给了它一个专业词 浅比较
 
- 总结
- PureComponent 会自动进行一次浅比较
- Component 不会自动进行比较的,需要我们手动在 shouldComponentUpdate 中比较
 
forceUpdate
- 强制渲染,会跳过 shouldComponentUpdate
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | import React, { Component } from "react";
 export default class App extends Component {
 name = "fox";
 
 setName = () => {
 this.name = "dog";
 
 
 
 
 this.forceUpdate();
 };
 render() {
 return (
 <div>
 <button onClick={this.setName}>修改</button>
 <p>{this.name}</p>
 </div>
 );
 }
 }
 
 | 
销毁阶段
- componentWillUnmount
- 触发条件: 组件被销毁了
- 作用
- 清除计时器、定时器
- 清除绑定在 window/document 身上的事件
- 清除第三方实例
 
 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 
 | import React, { Component } from "react";import _ from "lodash";
 export default class Hello extends Component {
 timer: any = null;
 lodash: any = null;
 
 componentDidMount() {
 this.lodash = _;
 this.timer = setInterval(() => {
 
 console.log("hello", this.lodash);
 }, 1000);
 window.onresize = function () {
 
 console.log("浏览器尺寸发生了改变");
 };
 }
 
 componentWillUnmount() {
 console.log("销毁了");
 clearInterval(this.timer);
 window.onresize = null;
 delete this.lodash;
 }
 
 render() {
 return <div>hello</div>;
 }
 }
 
 | 
错误处理阶段
- componentDidCatch
- 做什么的
- 写在哪里的?
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 
 | import React, { Component } from "react";import Hello from "./Hello";
 
 interface P {}
 
 interface S {
 errorFlag: boolean;
 }
 
 export default class App extends Component<P, S> {
 constructor(props: P) {
 super(props);
 this.state = {
 errorFlag: false,
 };
 }
 
 componentDidCatch(error: any, info: any) {
 console.log("触发");
 if (error) {
 this.setState({
 errorFlag: true,
 });
 }
 }
 
 render() {
 if (this.state.errorFlag) return <div> 回退UI</div>;
 return (
 <div>
 <Hello />
 </div>
 );
 }
 }
 
 | 
子组件在 componentDidMount 扔出一个错误
16 版本
- 挂载阶段
- componentWillMount[17 版本弃用了它,用了 static getDerivedStateFromProps]
- 更新阶段
- componentWillReceiveProps 因为 shouldComponentUpdate 也可以监听
- componentWillUpdate 因为造成异步滥用
15 版本
- 通过 React.createClass 来定义类组件的
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | import React from "react";
 export default React.createClass({
 getDefaultProps() {
 
 return {
 coloe: "黄皮肤",
 };
 },
 getInitailState() {
 
 return {
 count: 1,
 };
 },
 });
 
 | 
react 受控组件 & 非受控组件 & 半受控组件
受控组件 【表单元素】
- 表单元素的 value 受组件的 state 的控制,这个表单元素我们就称之为受控组件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | import React, { Component } from "react";
 interface P {}
 
 interface S {
 val: string;
 }
 
 export default class App extends Component<P, S> {
 constructor(props: P) {
 super(props);
 this.state = {
 val: "",
 };
 }
 
 setVal = (e: any) => {
 this.setState({
 val: e.target.value,
 });
 };
 render() {
 const { val } = this.state;
 return (
 <div>
 <input type="text" value={val} onChange={this.setVal} />
 </div>
 );
 }
 }
 
 | 
非受控组件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | import React, { Component } from "react";
 export default class App extends Component {
 render() {
 return (
 <div>
 表单元素自己管理自己的state <hr />
 我们可以认为input的value就是它自己的state <hr />
 表单元素自己管理自己的state,我们称这个表单为 非受控组件 <hr />
 {}
 <input defaultValue="hello" />
 </div>
 );
 }
 }
 
 | 
半受控组件
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 
 | import React, { Component } from "react";interface P {}
 interface S {
 initVal: string;
 }
 export default class App extends Component<P, S> {
 constructor(props: P) {
 super(props);
 
 this.state = {
 initVal: "hello",
 };
 }
 
 render() {
 return (
 <div>
 表单元素的初始值是由组件来管理的 <hr />
 表单元素value的变化还是交给了表单元素自己管理 <hr />
 这种类型我们称之为 半受控组件 <hr />
 <input defaultValue={this.state.initVal} />
 </div>
 );
 }
 }
 
 |