React-函数式组件和类式组件三大核心属性

1.组件核心属性之state

1.1类式组件state

1.1.1类式组件初始化state

import React, {
    
     Component } from 'react'

export default class Text extends Component {
    
    
  constructor(props) {
    
    
  	//构造器中的this就是组件的实例对象
    super(props);
    this.state = {
    
    //初始化state必须是一个对象
      msg: '欢迎使用React'
    }
  }
  render() {
    
    
    return (
      <div>
        <h2>{
    
    this.state.msg}</h2>
      </div>
    )
  }
}

1.1.2类式组件中的setState的两种写法

1.1.2.1类式组件中的setState-对象写法
  • setState(stateChange,[callback])-------对象式的setState
    • stateChange为状态改变对象(该对象可以体现出状态的更改)
    • callback是可选的回调函数,他在状态更新完毕,界面也更新之后(render调用后)才被调用
import React, {
    
     Component } from 'react'

export default class Text extends Component {
    
    
  state = {
    
    
    msg: '欢迎使用react',
    count: 0
  }
  add = (event, str) => {
    
    
    let {
    
     count } = this.state;
    switch (str) {
    
    
      case '非回调函数':
        this.setState({
    
    
          count: count + 1
        });
        console.log(this.state.count);
        break;
      case '回调函数':
        this.setState({
    
    
          count: count + 1
        }, () => {
    
    
          console.log('回调函数中的count', this.state.count);//回调函数中的count就是最新的count
        });
        console.log(this.state.count);//由于setState是一个异步操作,所以这里面的还是没修改之前的count
        break;
    }
  }
  render() {
    
    
    return (
      <div>
        <h2>{
    
    this.state.msg}</h2>
        <p>{
    
    this.state.count}</p>
        <button onClick={
    
    (event) => {
    
    
          this.add(event, '非回调函数')
        }}>+非回调函数 对象写法</button>
        <button onClick={
    
    (event) => {
    
    
          this.add(event, '回调函数')
        }}>+回调函数 对象写法</button>
      </div>
    )
  }
}
1.1.2.2类式组件中的setState-函数写法
  • setState(updater,[callback])------函数式的setState
    • updater为返回stateChange对象的函数
    • updater可以接收到stateprops
    • callback是可选的回调函数,他在状态更新完毕,界面也更新之后(render调用后)才被调用
import React, {
    
     Component } from 'react'

export default class Text extends Component {
    
    
  state = {
    
    
    msg: '欢迎使用react',
    count: 0
  }
  add = (event, str) => {
    
    
    switch (str) {
    
    
      case '非回调函数':
        this.setState((state, props) => {
    
    
          return {
    
    
            count: state.count + 1
          }
        });
        console.log(this.state.count);
        break;
      case '回调函数':
        this.setState((state, props) => {
    
    
          return {
    
    
            count: state.count + 1
          }
        }, () => {
    
    
          console.log('回调函数中的count', this.state.count);//回调函数中的count就是最新的count
        });
        console.log(this.state.count);//由于setState是一个异步操作,所以这里面的还是没修改之前的count
        break;
    }
  }
  render() {
    
    
    return (
      <div>
        <h2>{
    
    this.state.msg}</h2>
        <p>{
    
    this.state.count}</p>
        <button onClick={
    
    (event) => {
    
    
          this.add(event, '非回调函数')
        }}>+非回调函数 函数写法</button>
        <button onClick={
    
    (event) => {
    
    
          this.add(event, '回调函数')
        }}>+回调函数 函数写法</button>
      </div>
    )
  }

1.1.2类式组件中的事件

import React, {
    
     Component } from 'react'

export default class Text extends Component {
    
    
  constructor(props) {
    
    
    console.log('constructor');//构造器调用几次? ==>1次
    super(props);
    this.state = {
    
    
      msg: '欢迎使用React',
      bool: false
    };
    this.changeBool = this.changeBool.bind(this)//这句代码的意思为:找到Text原型上changeBool的方法,通过bind的方式将this指向Text的实例对象,并挂载到Text类的自身上
  }
  changeBool() {
    
    //调用几次? ==> 出发几次调用几次
    console.log('changeBool');
    // changeBool放在哪里? ------ Text的原型对象上,供Text的实例对象使用
    // 由于changeBool是作为onClick的回调函数,所以是不能通过实例调用的,是直接调用,如果不在构造器中纠正this的指向为Text的实例对象,那么这个this就应该指向window,但是类中的方法默认开启了局部的严格模式,所以changeBool中的this为undefined
    let {
    
     bool } = this.state;
    // 警告:状态state不可以直接更改,需要借助一个内置的API取更改 ==> setState
    bool=!bool;//这是错误的写法!!!
    this.setState({
    
    //这才是正确的写法,在这里面的更新是一种合并,而不是替换
      bool: !bool
    })
  }
  render() {
    
    //调用几次? ==> 1+n次 n就是状态更新的次数
    return (
      <div>
        <h2>{
    
    this.state.msg}</h2>
        {
    
    
          this.state.bool ? (<span></span>) : (<span></span>)
        }
        <button onClick={
    
    this.changeBool}>切换bool的真假</button>
      </div>
    )
  }
}

1.1.3类式组件的简写方式

import React, {
    
     Component } from 'react'

export default class Text extends Component {
    
    
  // 类中可以直接写赋值语句
  a = 996
  state = {
    
    //给类的自身添加state属性
    msg: '欢迎使用react',
    bool: true
  }
  changeBool = () => {
    
    //给类的自身添加方法 ==> 赋值语句+箭头函数 这里面的this就是类的实例对象
    let {
    
     bool } = this.state;
    this.setState({
    
    
      bool: !bool
    })
  }
  render() {
    
    
    console.log(this.a);//996
    return (
      <div>
        <h2>{
    
    this.state.msg}</h2>

        <button onClick={
    
    this.changeBool}>切换bool的真假</button>
      </div>
    )
  }
}

1.2函数式组件state

1.2.1函数式组件初始化state

  • State Hook让函数组件可以有state状态,并进行状态数据的读写操作
  • 语法:const [xxx,setxxx]=React.useState(initValue)
  • useState()说明:
    • 参数一:第一次初始化指定的值在内部缓存
    • 参数二:更新状态值的函数
import React, {
    
     Component } from 'react';

function Child() {
    
    
  const [count, addCount] = React.useState(1);
  const [msg, changeMsg] = React.useState('欢迎使用函数式组件');
  return (
    <div>
      <h3>这里是函数组件</h3>
      <p>{
    
    count}</p>
      <p>{
    
    msg}</p>
    </div>
  )
}

1.2.2函数式组件修改状态数据的两种写法

1.2.2.1函数式组件修改状态数据-非回调函数

  • setXxx(newValue):参数为非函数值,直接指定新的状态值,内部用其覆盖原来的状态值
import React, {
    
     Component } from 'react';

function Child() {
    
    
  const [count, addCount] = React.useState(1);
  function add(event, str) {
    
    
 	addCount(count + 1);
  }
  return (
    <div>
      <h3>这里是函数组件</h3>
      <p>{
    
    count}</p>
      <button onClick={
    
    (evnet) => {
    
    
        add(evnet, '非回调函数')
      }}>+ 非回调函数</button>
    </div>
  )
}

1.2.2.2函数式组件修改状态数据-回调函数

  • setXxx(value=>newValue):参数为函数,接受原来的状态值,返回新的状态值,内部用其覆盖原来的值
import React, {
    
     Component } from 'react';

function Child() {
    
    
  const [count, addCount] = React.useState(1);
  function add(event, str) {
    
    
    addCount((count) => {
    
    
      return count + 1
    })
  }
  return (
    <div>
      <h3>这里是函数组件</h3>
      <p>{
    
    count}</p>
      <button onClick={
    
    (evnet) => {
    
    
        add(evnet, '回调函数')
      }}>+ 回调函数</button>
    </div>
  )
}

1.3总结-对象式和函数式写法

  • 对象式setState是函数式setState简写方式(语法糖)
  • 使用原则
    • 如果新状态不依赖原状态==>使用对象方式
    • 如果新状态依赖原状态==>使用函数方式
    • 如果需要在setState()执行后获取最新的状态数据要在第二个callback函数中读取

2.组件核心属性之props

2.1类式组件props

2.1.1类式组件props的基本使用

import React, {
    
     Component } from 'react';

class Parent extends Component {
    
    
  render() {
    
    
    return (
      <div>
        <h3>Parent</h3>
        <Child str='字符串' num={
    
    9} bool={
    
    false} arr={
    
    [1, 1, 1]} obj={
    
    {
    
     name: '张三', age: 18 }} {
    
    ...{
    
     sex: '男', id: 10 }}></Child>
      </div>
    )
  }
}

class Child extends Component {
    
    
  changePropsValue = () => {
    
    
    let {
    
     str } = this.props;//字符串
    // 注意点props的值是只读属性,不能修改,修改就报错
    this.props.str = '修改字符串';//Uncaught TypeError: Cannot assign to read only property 'str' of object '#<Object>
  }
  render() {
    
    
    console.log(this.props);//{str: "字符串", num: 9, bool: false, arr: Array(3), obj: {…}, …}
    return (
      <div>
        <h3>Child</h3>
        <button onClick={
    
    this.changePropsValue}>修改props的值</button>
      </div>
    )
  }
}

2.1.2类式组件props传入值的限制(类型/必要性/默认值)

import React, {
    
     Component } from 'react';
import PropTypes from 'prop-types';

class Parent extends Component {
    
    
  render() {
    
    
    return (
      <div>
        <h3>Parent</h3>
        <Child str='字符串' num={
    
    9} bool={
    
    true} arr={
    
    [1, 1, 1]} obj={
    
    {
    
     name: '张三', age: 18 }} {
    
    ...{
    
     sex: '男', id: 10 }}></Child>
      </div>
    )
  }
}

class Child extends Component {
    
    
  static propTypes = {
    
    //限制传入的类型
    str: PropTypes.string.isRequired,//限制str的值类型为字符串且必填
    num: PropTypes.number,
    bool: PropTypes.bool,
    arr: PropTypes.array,
    obj: PropTypes.object
  }
  static defaultProps ={
    
    //设置传入值的默认值
    num:20,
    bool:false
  }
  
  render() {
    
    
    console.log(this.props);//{str: "字符串", num: 9, bool: false, arr: Array(3), obj: {…}, …}
    return (
      <div>
        <h3>Child</h3>
      </div>
    )
  }
}

2.1.3类式组件的构造器(constructor)和props的关系

  • 构造器是否接受props,是否传递给super,取决于是否希望在构造器中通过this访问props
2.1.3.1接props,把props传给在构造器(constructor)中调用super(props)
import React, {
    
     Component } from 'react';

class Parent extends Component {
    
    
  render() {
    
    
    return (
      <div>
        <h3>Parent</h3>
        <Child str='字符串' num={
    
    9} bool={
    
    true} arr={
    
    [1, 1, 1]} obj={
    
    {
    
     name: '张三', age: 18 }} {
    
    ...{
    
     sex: '男', id: 10 }}></Child>
      </div>
    )
  }
}

class Child extends Component {
    
    
  constructor(props) {
    
    
    super(props);
    console.log(this.props);//{str: "字符串", num: 9, bool: false, arr: Array(3), obj: {…}, …}
  }
  render() {
    
    
    return (
      <div>
        <h3>Child</h3>
      </div>
    )
  }
}
2.1.3.2不接props,不把props传给在构造器(constructor)中调用super()
import React, {
    
     Component } from 'react';

class Parent extends Component {
    
    
  render() {
    
    
    return (
      <div>
        <h3>Parent</h3>
        <Child str='字符串' num={
    
    9} bool={
    
    true} arr={
    
    [1, 1, 1]} obj={
    
    {
    
     name: '张三', age: 18 }} {
    
    ...{
    
     sex: '男', id: 10 }}></Child>
      </div>
    )
  }
}

class Child extends Component {
    
    
  constructor() {
    
    
    super();
    console.log(this.props);//undefined
  }
  render() {
    
    
    return (
      <div>
        <h3>Child</h3>
      </div>
    )
  }
}

2.2函数式组件props

2.2.1函数式组件props的基本使用

import React, {
    
     Component } from 'react';

class Parent extends Component {
    
    
  render() {
    
    
    return (
      <div>
        <h3>Parent</h3>
        <Child str='字符串' num={
    
    9} bool={
    
    true} arr={
    
    [1, 1, 1]} obj={
    
    {
    
     name: '张三', age: 18 }} {
    
    ...{
    
     sex: '男', id: 10 }}></Child>
      </div>
    )
  }
}

function Child(props) {
    
    
  console.log(props);//{str: "字符串", num: 9, bool: true, arr: Array(3), obj: {…}, …}
  return (
    <div>
      <h3>Child</h3>
    </div>
  )
}

2.2.2函数式组件props传入值的限制(类型/必要性/默认值)

import React, {
    
     Component } from 'react';
import PropTypes from 'prop-types';

class Parent extends Component {
    
    
  render() {
    
    
    return (
      <div>
        <h3>Parent</h3>
        <Child str='字符串' num={
    
    9} bool={
    
    true} arr={
    
    [1, 1, 1]} obj={
    
    {
    
     name: '张三', age: 18 }} {
    
    ...{
    
     sex: '男', id: 10 }}></Child>
      </div>
    )
  }
}

Child.propTypes = {
    
    //限制标签属性类型以及是否必填
  str: PropTypes.string.isRequired,//限制str的值类型为字符串且必填
  num: PropTypes.number,
  bool: PropTypes.bool,
  arr: PropTypes.array,
  obj: PropTypes.object
}

Child.defaultProps = {
    
    //设置传入值的默认值
  num: 20,
  bool: false
}

function Child(props) {
    
    
  console.log(props);//{str: "字符串", num: 9, bool: true, arr: Array(3), obj: {…}, …}
  return (
    <div>
      <h3>Child</h3>
    </div>
  )
}

3.组件核心属性值refs

3.1类式组件refs

3.1.1refs-字符串形式(不推荐,会有效率上的问题)

class Child extends Component {
    
    
  getInputValue = () => {
    
    
    let {
    
     inputDOM } = this.refs;
    console.log(inputDOM.value);
  }
  render() {
    
    
    return (
      <div>
        <h3>Child</h3>
        <input ref='inputDOM' type="text" />
        <button onClick={
    
    this.getInputValue}>获取input输入框的值</button>
      </div>
    )
  }
}

3.1.2refs-回调函数形式(推荐)

3.1.2.1refs-回调函数形式-内联函数绑定方式
class Child extends Component {
    
    
  strongUpdate = () => {
    
    //强制刷新
    this.forceUpdate();
  }
  getInputValue = () => {
    
    
    let {
    
     inputDOM } = this;
    console.log(inputDOM.value);
  }
  render() {
    
    
    return (
      <div>
        <h3 onClick={
    
    this.strongUpdate}>Child</h3>
        {
    
    /* 这个函数会自动执行,将[currentNode]挂载到this的实例上 随着render的每一次刷新,内联函数都是一个新的函数,这个都会重新执行,第一次为null(清空之前的) 第二次才是真的的dom节点 */}
        <input ref={
    
    (currentNode) => {
    
    
          console.log(currentNode);
          this.inputDOM = currentNode
        }} type="text" />
        <button onClick={
    
    this.getInputValue}>获取input输入框的值</button>
      </div>
    )
  }
}
3.1.2.1refs-回调函数形式-非内联函数绑定方式
class Child extends Component {
    
    
  strongUpdate=()=>{
    
    //强制刷新
    this.forceUpdate();
  }
  saveInputDOM = (currentNode) => {
    
    
    console.log(currentNode);
    this.inputDOM = currentNode;
  }
  getInputValue = () => {
    
    
    let {
    
     inputDOM } = this;
    console.log(inputDOM.value);
  }
  render() {
    
    
    return (
      <div>
        <h3 onClick={
    
    this.strongUpdate}>Child</h3>
        {
    
    /* 随着render的刷新,不会调用两次,所以不会出现null的情况 */}
        <input ref={
    
    this.saveInputDOM} type="text" />
        <button onClick={
    
    this.getInputValue}>获取input输入框的值</button>
      </div>
    )
  }
}

3.1.3refs-createRef形式(推荐)

class Child extends Component {
    
    
  inputDOM = React.createRef()//定义一个ref容器
  h2DOM = React.createRef()//定义一个ref容器
  getInputValue = () => {
    
    
    console.log(this.h2DOM.current);
    console.log(this.inputDOM.current.value);
  }
  render() {
    
    
    return (
      <div>
        <h3 ref={
    
    this.h2DOM}>Child</h3>
        <input ref={
    
    this.inputDOM} type="text" />
        <button onClick={
    
    this.getInputValue}>获取input输入框的值和button</button>
      </div>
    )
  }
}

3.2函数式组件refs

  • Ref Hook可以在函数中存储/查找组件内标签或者任意其他数据
  • 语法const inputDOM = React.useRef()
  • 作用:保存标签对象 和React.createRef一样
function Child() {
    
    
  const inputDOM=React.useRef();
  function getInputValue(){
    
    
    console.log(inputDOM.current.value);
  }
  return (
    <div>
      <h3>Child</h3>
      <input ref={
    
    inputDOM} type="text" />
      <button onClick={
    
    getInputValue}>获取input输入框的值和button</button>
    </div>
  )
}

猜你喜欢

转载自blog.csdn.net/big_sun_962464/article/details/113360796
今日推荐