前言
React的类组件(Class Component)学习笔记
定义组件
- 组件名首字母大写
- 必须继承
React.Component类
- 必须重写
render()方法,并返回React组件对象
- 每个React组件只能由一个根组件构成,组件内可以包含任意数量的子组件
return可以返回的数据类型
- 返回React组件对象,渲染为DOM
- 每当使用
return返回组件时,推荐使用()进行包裹,便于与原始JS代码区分
- 返回字符串或数值类型数据,直接渲染
- 返回null或布尔类型数据,不渲染任何内容
- 返回数组或fragments
- 返回Portals
- 使用组件时,既可以使用单标签引入,也可以使用双标签引入
1 2 3 4 5 6 7 8 9 10 11
| import React from "react";
class Component extends React.Component { render() { return ( <></> ); } }
export default Component;
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| import React from "react";
class Component extends React.Component { render() { return ( <> <div className=""></div> </> ); } }
export default Component;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import React from "react";
class Component extends React.Component { render() { return ( <> <label htmlFor="input"> <input id="input" type="text" /> </label> </> ); } }
export default Component;
|
定义纯组件
- 通过集成
React.PureComponent类创建的组件,内部实现了性能优化
- 浅比较
props和state,如果浅比较结果相同,则不重新渲染当前组件
1 2 3 4 5 6 7 8 9 10 11
| import React from "react";
class Component extends React.PureComponent { render() { return ( <></> ); } }
export default Component;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import React from "react";
class Component extends React.Component { constructor(props) { super(props);
this.state = {}; }
shouldComponentUpdate(nextProps, nextState) { return !(shallowEqual(this.props, nextProps) && shallowEqual(this.state, nextState)); }
render() { return ( <></> ); } }
function shallowEqual(objA, objB) { ... }
export default Component;
|
定义组件的实例方法
- 在
render()中使用实例方法时,需要重新绑定this,才能在实例方法中使用this
只有event参数的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.fn = this.fn.bind(this); }
fn(event) { ... }
render() { return ( <> <div onClick={ this.fn }></div> </> ); } }
export default Component;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Component extends React.Component {
fn(event) { ... }
render() { return ( <> <div onClick={ this.fn.bind(this) }></div> </> ); } }
export default Component;
|
- 不使用实例方法,改为使用实例属性,并且属性值是箭头函数定义的函数,这种方式无需显式绑定
this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Component extends React.Component {
fn = (event) => { ... }
render() { return ( <> <div onClick={ this.fn }></div> </> ); } }
export default Component;
|
- 不使用实例方法,改为直接使用箭头函数,箭头函数执行需要调用的实例方法,这种方式无需显示绑定
this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Component extends React.Component {
fn = (event) => { ... }
render() { return ( <> <div onClick={ (event) => this.fn(event) }></div> </> ); } }
export default Component;
|
除了event参数还包含其他自定义参数的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Component extends React.Component {
fn(arg, event) { ... }
render() { return ( <> <div onClick={ this.fn.bind(this, "value") }></div> </> ); } }
export default Component;
|
- 不使用实例方法,改为直接使用箭头函数,箭头函数执行需要调用的实例方法,这种方式无需显示绑定
this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Component extends React.Component {
fn = (event, arg) => { ... }
render() { return ( <> <div onClick={ (event) => this.fn(event, "value") }></div> </> ); } }
export default Component;
|
组件的状态
定义组件的状态
渲染值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { key: "value" }; }
render() { return ( <> <div>{ this.state.key }</div> </> ); } }
export default Component;
|
渲染数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { key: [] }; }
render() { return ( <> <ul>{ this.state.key.map(item -> <li>{ item }</li>) }</ul> </> ); } }
export default Component;
|
修改组件的状态
- 通过
this.setState()在组件的实例方法中修改组件的状态
- 通过
this.setState()修改组件的状态时,只会修改实参对象中定义的属性,而不会覆盖其他属性(本质是做了对象合并)
- 通过
this.setState()修改组件的状态完成后,会自动执行render()重新渲染DOM
传递对象
1 2 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 from "react";
class Component extends React.Component {
constructor() { super();
this.state = { key: "default" };
this.fn = this.fn.bind(this); }
fn() { this.setState({ key: "value" }); }
render() { return ( <> <div onClick={ this.fn }>{ this.state.key }</div> </> ); } }
export default Component;
|
- 如果修改的状态是引用类型(比如修改对象的属性或修改数组的元素),需要覆盖整个对象,而不是直接修改对象
1 2 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
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { obj: { key: "default" } };
this.fn = this.fn.bind(this); }
fn() { const copyObj = Object.assign(new Object(), originalObj); copyObj.key = "value"; this.setState({ obj: copyObj }); }
render() { return ( <> <div onClick={ this.fn }>{ this.state.obj.key }</div> </> ); } }
export default Component;
|
传递函数
1 2 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
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { key: "default" };
this.fn = this.fn.bind(this); }
fn() { this.setState((state, props) => { return { key: "value" } }); }
render() { return ( <> <div onClick={ this.fn }>{ this.state.key }</div> </> ); } }
export default Component;
|
修改完成的回调函数
setState()修改组件状态操作是异步的,如果需要在修改完成之后才执行的逻辑,可以通过setState()的第二个参数传入回调函数实现
1 2 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
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { key: "default" };
this.fn = this.fn.bind(this); }
fn() { this.setState({ key: "value" }, function () { ... }); }
render() { return ( <> <div onClick={ this.fn }>{ this.state.key }</div> </> ); } }
export default Component;
|
强制同步修改
1 2 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
| import React from "react"; import { flushSync } from "react-dom";
class Component extends React.Component {
constructor() { super();
this.state = { key: "default" };
this.fn = this.fn.bind(this); }
fn() { flushSync(() => { this.setState({ key: "value" }); }); }
render() { return ( <> <div onClick={ this.fn }>{ this.state.key }</div> </> ); } }
export default Component;
|
强制刷新状态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import React from "react";
class Component extends React.Component {
constructor() { super(); }
fn() { this.forceUpdate(); }
render() { return ( <> <div onClick={ this.fn }></div> </> ); } }
export default Component;
|
生命周期函数
- 组件挂载:
constructor()创建组件实例=>getDevicedStateFromProps()=>render()重新渲染虚拟DOM=>渲染真实DOM=>componentDidMount()完成组件挂载
- 组件更新:
getDevicedStateFromProps()=>shouldComponentUpdate()预检查是否更新,如果返回false就不更新=>render()重新渲染虚拟DOM=>getSnapshopBeforeUpdate()=>componentDidUpdate(prevProps, prevState, snapshot)完成组件更新
- 组件卸载:
componentWillUnmount()完成组件卸载
1 2 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
| import React from "react";
class Component extends React.Component { constructor() { super(); } render() { ... }; conponentDidMount() { ... }; componentDidUpdate(prevProps, prevState, snapshot) { ... }; componentWillUnmount() { ... }; shouldComponentUpdate(nextProps, nextState) { return true; } getSnapshopBeforeUpdate() { ... } }
export default Component;
|
父子组件数据传递
父组件传递数据给子组件
- 子组件接收父组件可能传递的数据
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.key1 }</div> </> ) } }
export default Son;
|
- 父组件传递数据给子组件
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from "react"; import Son from "./Son";
class Father extends React.Component { render() { return ( <> <Son key1={ "value" } /> </> ); } }
export default Father;
|
子组价接收数据时定义数据类型
src/Son.jsx1 2 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
| import React from "react"; import PropTypes from "prop-types";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.key1 }</div> </> ) } }
Son.propTypes = { key1: PropTypes.string.isRequired, key2: PropTypes.number, key3: PropTypes.bool, key4: PropTypes.object, key5: PropTypes.array, key6: PropTypes.func, }
export default Son;
|
子组价接收数据时定义默认值
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import React from "react";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.key1 }</div> </> ) } }
Son.defaultProps = { key1: "default" }
export default Son;
|
src/Son.ES18.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import React from "react";
class Son extends React.Component {
static defaultProps = { key1: "default" }
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.key1 }</div> </> ) } }
export default Son;
|
父组件通过对象的展开运算符传递多个数据
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import React from "react"; import Son from "./Son";
class Father extends React.Component { render() { const obj = { key1: "value", key2: "value" }
return ( <> <Son key1={ "value" } key2={ "value" } /> <Son { ...obj } /> </> ); } }
export default Father;
|
子组件传递事件给父组件
- 子组件调用父组件传递的函数参数
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import React from "react";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <>{ this.props.key("payload") }</> ); } }
export default Son;
|
- 父组件传递函数作为参数给子组件
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React from "react"; import Son from "./Son";
class Father extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <Son key={ (payload) => {console.log(payload)} } /> </> ); } }
export default Father;
|
插槽
通过children实现插槽
- React中没有插槽的概念,但是可以在子组件中通过
props.children获取父组件传递的元素
传递一个子元素
- 如果父组件调用子组件时传递一个子元素,那么
props.children是这个子元素对象
- 子组件接收父组件可能传递的元素
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.children }</div> </> ) } }
export default Son;
|
- 父组件传递元素给子组件
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import React from "react"; import Son from "./Son";
class Father extends React.Component { render() { return ( <> <Son> <div></div> </Son> </> ); } }
export default Father;
|
子组件通过定义参数数据类型实现限制子元素个数
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import React from "react"; import PropTypes from "prop-types";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.children }</div> </> ) } }
Son.propTypes = { children: PropTypes.element }
export default Son;
|
传递多个子元素
- 如果父组件调用子组件时传递多个子元素,那么
props.children是这些子元素对象数组
- 子组件接收父组件可能传递的元素
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React from "react";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.children[0] }</div> <div>{ this.props.children[1] }</div> </> ) } }
export default Son;
|
- 父组件传递元素给子组件
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React from "react"; import Son from "./Son";
class Father extends React.Component { render() { return ( <> <Son> <div></div> <div></div> </Son> </> ); } }
export default Father;
|
通过props实现插槽
- 子组件接收父组件可能传递的元素
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import React from "react";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div> { this.props.key1 } { this.props.key2 } </div> </> ) } }
export default Son;
|
- 父组件传递元素给子组件
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from "react"; import Son from "./Son";
class Father extends React.Component { render() { return ( <> <Son key1={ <div></div> } key2={ <div></div> } /> </> ); } }
export default Father;
|
通过props传递函数实现作用域插槽
- 子组件接收父组件可能传递的元素
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import React from "react";
class Son extends React.Component {
constructor(props) { super(props); }
render() { return ( <> <div>{ this.props.key("context") }</div> </> ) } }
export default Son;
|
- 父组件传递元素给子组件
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from "react"; import Son from "./Son";
class Father extends React.Component { render() { return ( <> <Son key={ (context) => <div>{ context }</div> } /> </> ); } }
export default Father;
|
父子组件跨多级传递数据
祖先组件传递数据给子孙组件
创建上下文对象
src/AppContext.jsx1 2 3 4 5
| import React from "react";
const AppContext = React.createContext();
export default AppContext;
|
定义默认值
src/AppContext.jsx1 2 3 4 5
| import React from "react";
const AppContext = React.createContext({key: "default"});
export default AppContext;
|
组件组件向子孙组件传递数据
- 使用上下文对象的
Provider组件包裹子组件
- 在上下文对象的
Provider组件定义value属性,通过value属性向子孙传递数据
src/GrandFather.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import React from "react"; import AppContext from "./AppContext"; import Father from "./Father";
class GrandFather extends React.Component { render() { return ( <> <AppContext.Provider value={ {key: "value"} }> <Father /> </AppContext.Provider> </> ); } }
export default GrandFather;
|
src/Father.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from "react"; import Son from "./Son";
class Father extends React.Component { render() { return ( <> <Son /> </> ); } }
export default Father;
|
子孙组件获取祖先组件传递的数据
通过上下文对象获取数据
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import React from "react"; import AppContext from "./AppContext";
class Son extends React.Component { render() { return ( <> { this.context.key } </> ); } }
Son.contextType = AppContext;
export default Son;
|
通过向Customer中传递回调函数获取数据
src/Son.jsx1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import React from "react"; import AppContext from "./AppContext";
class Son extends React.Component { render() { return ( <> <AppContext.Consumer> { (context) => { return context.key; } } </AppContext.Consumer> </> ); } }
export default Son;
|
src/Son.jsx1 2 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
| import React from "react"; import AppContext from "./AppContext";
class Son extends React.Component { render() { return ( <> <App1Context.Consumer> { (context) => { return context.key; } } </App1Context.Consumer> <App2Context.Consumer> { (context) => { return context.key; } } </App2Context.Consumer> </> ); } }
export default Son;
|
获取组件的原生DOM对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.divRef = React.createRef();
this.fn = this.fn.bind(this); }
fn() { const element = this.divRef.current; }
render() { return ( <> <div ref={ this.divRef }></div> </> ); } }
export default Component;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.fn = this.fn.bind(this); }
fn(element) { ... }
render() { return ( <> <div ref={ (element) => this.fn(element) }></div> </> ); } }
export default Component;
|
受控组件和非受控组件
受控组件
文本框和文本域
- 如果文本框设置了
value属性,这个组件就变成了受控组件,受控组件必须设置onChange属性,否则会导致表单元素的内容无法被修改
1 2 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 from "react";
class Component extends React.Component {
constructor() { super();
this.state = { key: "" };
this.fn = this.fn.bind(this); }
fn(event) { this.setState({ key: event.target.value }); }
render() { return ( <> <input type="text" value={ this.state.key } onChange={ (event) => this.fn(event) } /> </> ); } }
export default Component;
|
定义通用的受控组件处理函数
1 2 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
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { username: "", password: "" };
this.fn = this.fn.bind(this); }
fn(event) { this.setState({ [event.target.name]: event.target.value }); }
render() { return ( <> <input type="text" name={ this.state.username } value={ this.state.username } onChange={ (event) => this.fn(event) } /> <input type="text" name={ this.state.password } value={ this.state.password } onChange={ (event) => this.fn(event) } /> </> ); } }
export default Component;
|
单选框和多选框
- 如果选框设置了
checked属性,这个组件就变成了受控组件,受控组件必须设置onChange属性,否则会导致表单元素的内容无法被修改
单选
1 2 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 from "react";
class Component extends React.Component {
constructor() { super();
this.state = { isChecked: false };
this.fn = this.fn.bind(this); }
fn(event) { this.setState({ isChecked: event.target.checked }); }
render() { return ( <> <input type="checkbox" checked={ this.state.isChecked } onChange={ (event) => this.fn(event) } /> </> ); } }
export default Component;
|
多选
1 2 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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { arr: [ { label: "label1", isChecked: false }, { label: "label2", isChecked: false } ] };
this.fn = this.fn.bind(this); }
fn(event, label) { const copyArr = this.state.list.slice(0); copyArr.map((item) => { if (label === item.label) { item.isChecked = event.target.checked; } }); this.setState({ arr: copyArr }); }
render() { return ( <> { this.state.arr.map((item) => { return ( { item.label } <input type="checkbox" checked={ item.isChecked } onChange={ (event) => this.fn(event, item.label) } /> ); }); } </> ); } }
export default Component;
|
下拉选框
1 2 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
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { key: "" };
this.fn = this.fn.bind(this); }
fn(event) { this.setState({ key: event.target.value }); }
render() { return ( <> <select value={ this.state.key } onChange={ (event) => this.fn(event) }> <option value="value">value</option> </select> </> ); } }
export default Component;
|
多选
1 2 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
| import React from "react";
class Component extends React.Component {
constructor() { super();
this.state = { arr: [] };
this.fn = this.fn.bind(this); }
fn(event) { const values = Array.from(event.target.selectedOptions, (item) => item.value); this.setState({ arr: values }); }
render() { return ( <> <select value={ this.state.arr } onChange={ (event) => this.fn(event) } multiple> <option value="value">value</option> </select> </> ); } }
export default Component;
|
阻止表单元素刷新页面
1 2 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 from "react";
class Component extends React.Component {
constructor() { super();
this.fn = this.fn.bind(this); }
fn(event) { event.preventDefault();
...
}
render() { return ( <> <form onSubmit={ (event) => this.fn(event) }> <input type="submit" /> </fotm> </> ); } }
export default Component;
|
非受控组件
定义默认值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import React from "react";
class Component extends React.Component { constructor() { super();
this.state = { key: "default" }; }
render() { return ( <> <input type="text" defaultValue={ this.state.key } /> </> ); } }
export default Component;
|
完成