创建Class组件

  1. import React from 'react'
  2. class B extends React.Component {
  3. constructor(props) {
  4. super(props)
  5. }
  6. render() {
  7. return <div>hi</div>
  8. }
  9. }
  10. export default B

Props(外部数据)

初始化

  1. class B extends React.Component {
  2. // 初始化必须写全套
  3. constructor(props) {
  4. super(props);
  5. }
  6. render(){}
  7. }

读取 this.props.xxx

  1. class B extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. }
  5. render(){
  6. return <div onClick={this.props.onClick}>
  7. {this.props.name}
  8. <div>
  9. {this.props.children}
  10. </div>
  11. </div>
  12. }

相关钩子(已经不用了)

  1. // 用来检测props的变化
  2. componentWillReceiveProps(nextProps, nextContext) {
  3. console.log('props变化了');
  4. }

作用

  1. 接受外部数据
    只能读不能写
    外部数据由父组件传递

  2. 接受外部函数
    在恰当的时机,调用该函数
    该函数一般是父组件的函数

state(内部数据)

初始化

  1. class B extends React.Component {
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. user: {name:'frank', age:18}
  6. }
  7. }
  8. render() { /* ... */ }
  9. }

读this.state

  1. // this.state.xxx.yyy
  2. {this.state.user.name}
  3. {this.state.user.age}

写this.setState(???,fn)

  1. this.setState(newState,fn)
  2. this.setState({x: this.state.x + 1})
  3. // 写法二
  4. this.setState((state,props)=>newState,fn) // fn 会在成功后执行回调
  5. // 函数写法
  6. this.setState((state) => ({x: state.x + 1}))

注意setState不会立刻改变this.state,会在当前代码运行完后,再去更新this.state,从而触发UI更新。

在写时:setState会自动将新state与旧state进行一-级合并。

生命周期

官方文档

constructor() -在这里初始化state
shouldComponentUpdate() - return false阻止更新
render() -创建虚拟DOM
componentDidMount() -组件已出现在页面
componentDidUpdate() -组伴已更新
componentWillUnmount() -组件将死

constructor(初始化)

官方文档

初始化 props

初始化 state

用来写 bind this

render(渲染)

官方文档

用途
展示视图

  1. return (<div>...</div>) // 虚拟DOM

只能有一个根元素

如果有两个根元素,就要用<React.Fragment>包起

<React.Fragment />可以缩写成<></>

技巧

render里面可以写if.. .else

  1. render(){
  2. if(this.state.n % 2 ===0){
  3. return <div>偶数</div>
  4. }else {
  5. return <div>奇数</div>
  6. }
  7. }

render里面可以写?:表达式

  1. {this.state.n % 2 === 0 ? <div>偶数</div> : <div>奇数</div>}

render里面不能直接写for循环,需要用数组

render里面可以写array.map (循环)

  1. render(){
  2. return this.state.array.map(n=><div>{n}</div>)
  3. }

componentDidMount(组件已挂载)

官方文档

用途

在元素插入页面后执行代码,这些代码依赖DOM

比如你想获取div的高度,就最好在这里写

此处可以发起加载数据的AJAX请求(官方推荐)

首次渲染会执行此钩子

  1. componentDidMount() {
  2. const div = document.getElementById('xxx')
  3. const {width} = div.getBoundingClientRect()
  4. this.setState({width})
  5. }

shouldComponentUpdate(组件是否更新)

官方文档

它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活地设置返回值,以避免不必要的更新

返回true表示不阻止UI更新

返回false表示阻止UI更新

  1. onClick = () => {
  2. this.setState(state => ({
  3. n: state.n + 1
  4. }))
  5. this.setState(state => ({
  6. n: state.n - 1
  7. }))
  8. // 看似值没有变 但是产生了一个新的对象
  9. }
  10. shouldComponentUpdate(nextProps, nextState, nextContext) {
  11. return nextState.n !== this.state.n;
  12. }

这个钩子可以采取了内置功能 React.pureComponent

PureComponent 会在 render 之前对比新 state 和旧 state 的每一个 key,以及新 props 和旧 props 的每一个 key。
如果所有 key 的值全都一样,就不会 render;如果有任何一个 key 的值不同,就会 render。

  1. class App extends React.pureComponent {
  2. ...
  3. }

componentDidUpdate(组件已更新)

官方文档

用途

在视图更新后执行代码

此处也可以发起AJAX请求,用于更新数据(看文档)

首次渲染不会执行此钩子

在此处setState可能会引起无限循环,

除非放在if 里

若shouldComponentUpdate返回false,则不触发此钩子

componentWillUnmount(组件将死)

官方文档

用途
组件将要被移出页面然后被销毁时执行代码
unmount过的组件不会再次mount

举例

如果你在componentDidMount里面监听了window scroll,那么你就要在componentWillUnmount里面取消监听

如果你在componentDidMount里面创建了Timer,那么你就要在componentWillUnmount里面取消Timer

如果你在componentDidMount里面创建了AJAX 请求,那么你就要在componentWillUnmount里面取消请求

钩子运动图

37 React Class 组件详解 - 图1