(React全解)Class组件详解

一. class 组件创建方式
import React from 'react';

class B extends React.Component {
  constructor(props){
    super(props);
  }
  render(){
    return (
      <div>hi</div>
    )
  }
}
二. Props 外部数据
class Parent extends React.Component {
  constructor(props){
    super(props)
    this.state = {name:'frank'}
  }
  onClick = ()=>{}
  render(){
    return <B name={this.state.name} onClick={this.onClick}>hi</B>
  } // 这里的name和onClick就是props,来源是从this.state来的,是从外部来的作为props
}

// props如何初始化,这样子做了之后this.props就是外部数据的对象地址了
class B extends React.Component {
  constructor(props){
    super(props);
  }
  render(){

  }
}

// 读取props
class B extends React.Component {
  constructor(props){
    super(props);
  }
  render(){
    return <div onClick={this.props.onClick}>
      {this.props.name}
      <div>
        {this.props.children}
      </div>
    </div>
  }
}

// 不能去写props,外部数据应该由外部更新
三. componentWillReceiveProps 的作用
  • 接收外部数据,只能读不能写,外部呀数据由父组件传递
  • 接受外部函数,在恰当的时机调用该函数,该函数一般是父组件的函数
import React from 'react';

class App extends React.Component {
  constructor(props){
    super(props)
    this.state = {x : 1}
  }

  onClick = () => {
    this.setState({
      x: this.state.x + 1
    })
  }

  render(){
    return (
      <div className="App">
        App <button onClick={this.onClick}>+1</button>
        <B name={this.state.x}/>
      </div>
    );
  }
}

class B extends React.Component {
  UNSAFE_componentWillReceiveProps(newProps, nextContext) {
    console.log('旧的 props')
    console.log(this.props)
    console.log('props变化了')
    console.log('新的p props')
    console.log(newProps)
  }
  render(){
    return (
      <div>{this.props.name}</div>
    )
  }
}

export default App;
四. State & setState 内部数据
  • 初始化 State
class B extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      user: {name:'frank', age:187}
    }
  }
  render(){

  }
}
  • setState 的两种方式,推荐写成函数的形式,一般就用第一个参数,还有第二个参数接受成功之后的回调函数,另外写 state 的时候会进行一级合并(shallow merge)
  onClick = () => {
    this.setState({
      x: this.state.x + 1
    })
    this.setState({
      x: this.state.x + 1
    })
  }

  onClick2 = () => {
    this.setState((state)=>({x:state.x+1}))
    this.setState((state)=>({x:state.x+1}))
  }
五. 生命周期
let div = document.createElement('div')
// 这是div的 create/construct 过程
div.textContent = 'hi'
// 这是初始化state
document.body.appendChild(div)
// 这是div的mount过程
div.textContent = 'hi2'
// 这是div的update过程
div.remove()
// 这是div的unmount过程
  • 函数列表,以下是常用的

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

    • 初始化props

    • 初始化state,但此时不能调用setState

    • 用来写bind this

        constructor(){
            this.onClick = this.onClick.bind(this)
        }
        可以用新语法代替
        onClick = ()=> {}
        constructor() {
      
        }
    • 可不屑

  • shouldComponentUpdate的用途

    • 返回true表示不阻止UI更新
    • 返回false表示阻止UI更新
    • 示例见下页
    • 面试常问: shouldComponentUpdate有什么用?
    • 答: 它允许我们手动判断是否要进行组件更新,我们可以根据应用场景灵活地设置返回值,以避免不必要的更新
  • React.PureComponent会对state和props进行浅对比,就不需要shouldComponentUpdate了

  • render的用途

    • 展示视图,

      // return 对应的对象是不是一个dom元素, 而是一个表示dom元素的对象, 我们称其虚拟dom 
      return (<div>...</div>)
    • 只能有一个根元素

      用React.Fragment做占位,也可以写成<></>,两者等价
      • 技巧
        // render里面可以写if...else
        // 可以写?:
        // 不能直接写for,需要用数组
        // 可以写array.map 
        

      import React from 'react';

      class App extends React.PureComponent { constructor(props){

      super(props)
      this.state = {
        n:1
      }

      } onClick= ()=>{

      this.setState(state=> ({
        n: state.n+1
      }))

      }

      render(){

      console.log('render了一次')
      let message
      if(this.state.n % 2 === 0 ) {
        message = <div>偶数</div>
      } else {
        message = <span>奇数</span>
      }
      return (
        <>
          {message}
          <button onClick={ this.onClick }>+1</button>
        </>
      )

      } }

      export default App; // 循环的写法 render() { return this.state.array.map(n=>{n}) }

      - componentDidMount()的用途
        - 在元素插入页面后执行代码,这些代码依赖DOM
        - 比如你想获取div的高度,就最好在这里写
        - 此处可以发起加载数据的AJAX请求(官方推荐)
        - 首次渲染会执行此钩子

      componentDidMount() { const div = document.getElementById('xxx') const {width} = div.getBoundingClientRect() // console.log(width) this.setState({width}) }

      render(){

      return(
        <div id='xxx'>Hello World, {this.state.width}
        </div>
      )

      } ```

      • 也可以用ref来做

        import React from 'react';
        
        class App extends React.PureComponent {
          constructor(props){
            super(props)
            this.state = {
              n:1,
              width: undefined
            }
            this.divRef = React.createRef()
          }
          onClick= ()=>{
            this.setState(state=> ({
              n: state.n+1
            }))
          }
        
          componentDidMount() {
            const div = this.divRef.current
            const {width} = div.getBoundingClientRect()
            // console.log(width)
            this.setState({width})
          }
        
          render(){
            return(
              <div ref={this.divRef}>Hello World, {this.state.width}px
              </div>
            )
          }
        }
        
        export default App;
        
    • componentDidUpdate()的作用

      • 在视图更新后执行代码
      • 此处也可以发起AJAX请求,用于更新数据(看文档)
      • 首次渲染不会执行此钩子
      • 在此处setState可能会引起无限循环,除非放在if里
      • 若componentDidUpdate返回false,则不触发此钩子
      • componentWillUnmount的用途
      • 组件将要被移除页面然后被销毁时执行的代码
      • unmount过的组件不会再次mount
      • 举例:
        如果你在componentDidMount里面监听了window scroll
        那么就要在componentWillUnmount的用途里面取消监听
        如果你在componentDidMount里面创建了Timer
        那么就要在componentWillUnmount里面取消Timer
        如果你在componentDidMount里面创建了AJAX请求,这种情况比较特殊,数据还没回来你就死了 
        那么就要在componentWillUnmount里面取消请求
    • 总结:

      • 能用函数组件就用函数组件,能用purecomponent就用purecomponent,最后不行采用 react.component
      • 生命周期函数 生命周期.png
最后,个人微信,欢迎交流,提供工作机会。

wechat0.jpg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值