React理解 - 第三篇(有状态与无状态组件)

73 阅读2分钟

组件分为两种

  1. 无状态组件(函数式组件)无状态组件可以通过props的形式来达到响应式变化
// 无状态组件 函数式组件
// 静态组件 没有状态 无法修改内容
function App() {
  var count = 0
  setInterval(() => {
    count++
    /**
     * 时间调用定时器函数 每次调用count值都会变化 
     * 每次调用都会log一个count1 但状态没变 所以不会渲染页面
     * */ 
    console.log('count1', count)
  }, 1000)
  // 在此处只会log一次也就是初始渲染 因为没有状态修改 所以不会重新渲染 所以不会进行到这一步
  console.log('count2', count)
  var data = {
    name: 'jack'
  }
  var arr = [1, 2, 3]
  var isMan = false
  var getName = () => {
    return '我是函数'
  }
  return (
    // jsx中必须使用一个父级标签包裹 可以使用一个Fragment
    <>
      <h1 className='app'>{count}</h1>
      <h1 className='app'>{data.name}</h1>
      <h1 className='app'>{arr[1]}</h1>
      <h1 className='app'>{isMan ? "woman" : "man"}</h1>
      <h1 className='app'>{getName()}</h1>
    </>
  )
}
  1. 有状态组件 (有state的组件)
  • 老版本:this.state = {} 调用的时候使用this.state.key来调用,修改的时候使用this.setState({key: value})
class App extends React.Component {
  // state(状态)
  // 在组件内修改数据使用state
  constructor(props) {
    super(props)
    this.state = {
      count: 0,
      door: 'open'
    }
    setInterval(() => {
      // this.state.count++
      this.setState({
        // count: this.state.count++ 只有执行完后才会++ 我已经先setState之后在修改了值 将一直为0
        // count: ++this.state.count 目的可以达成
        count: this.state.count + 1
      })
    }, 1000)
  }
  
  handleClick() {
    console.log('this', this)
    // this的值为undefined
    this.setState({
      door: 'close'
    })
  }

  // 是个独立的作用域 通过this.state来拿值
  render() {
    // es6的解构
    const { count, door } = this.state
    return (
      <>
        <h1 className='app'>{count}</h1>
        {/* 用箭头函数来传递特定的参数 但是使用这种绑定this的方法 每次render都会生成新的函数实例 影响性能 */}
        {/* <h1 onClick={(e) => this.handleClick('e', e)}>{door} 事件绑定</h1> */}
        <h1 onClick={this.handleClick.bind(this)}>{door} 事件绑定</h1> 
      </>
    )
  }
}

方法二:

class App extends React.Component {
  // state(状态)
  // 在组件内修改数据使用state
  constructor(props) {
    super(props)
    this.state = {
      door: 'open'
    }
    // 绑定this的作用域
    this.handleClick = this.handleClick.bind(this)
  }
  
   handleClick() {
    console.log('this', this)
    this.setState({
      door: 'close'
    })
  }

  // 是个独立的作用域 通过this.state来拿值
  render() {
    // es6的解构
    const { door } = this.state
    return (
      <>
        <h1 onClick={this.handleClick}>{door}事件绑定</h1>
      </>
    )
  }
}

方法三:

class App extends React.Component {
  // state(状态)
  // 在组件内修改数据使用state
  constructor(props) {
    super(props)
    this.state = {
      door: 'open'
    }
  }

  // 默认传递事件对象
  // 箭头函数的this在babel编译的时候 会默认绑定this
  // 使用了箭头函数时 不需要在constructor中绑定this的作用域
  handleClick = () => {
    console.log('this', this)
    this.setState({
      door: 'close'
    })
  }

  // 是个独立的作用域 通过this.state来拿值
  render() {
    // es6的解构
    const { door } = this.state
    return (
      <>
        <h1 onClick={this.handleClick}>{door} 事件绑定</h1> 
      </>
    )
  }
}
  • 新版本:const [value, setValue] = useState(value)(value可以是任何类型的值),调用的时候直接使用value,修改的时候直接使用setValue(newValue)
import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        // 点击button之后并不会递增三次 将只会递增一次 
        // 因为React 会等到事件处理函数中的 所有代码都运行完毕再处理你的 state 更新 所以number三次+1用的都是同一个值
        setNumber(number + 1);
        setNumber(number + 1);
        setNumber(number + 1);
      }}>+3</button>
    </>
  )
}