React学习(二、相关语法与组件通讯)

目录

一、组件的状态

类组件的状态

二、组件中的事件处理

1、事件绑定

2、事件处理与setState

事件对象

this指向

setState 修改状态

三、非受控组件-Ref的使用

四、组件通讯

1、父传子

2、子传父

3、兄弟组件通讯

4、跨级组件通讯

五、总结


一、组件的状态

在react中,组件分为有状态组件和无状态组件,具体为以下所示:

(1)函数组件又叫做无状态组件 函数组件在不考虑 hooks 的情况下是不能自己提供数据的;
(2)类组件又叫做有状态组件 类组件可以通过state自己提供数据;
(3)函数组件是没有状态的,只负责页面的展示;
(4)类组件有自己的状态,负责更新UI,只要类组件的数据发生了改变,UI 就会发生更新。

类组件的状态

(1)状态state,即数据,是组件内部的私有数据,只能在组件内部使用;
(2)状态 state 的值是对象,表示一个组件中可以有多个数据;
(3)通过 this.state.xxx 来获取状态。

class Hello extends React.Component {
  state = {
    count: 0,
  };
  render() {
    return (
      <>
        <p>当前值为:{this.state.count}</p>
      </>
    );
  }
}
ReactDOM.render(<Hello />, document.querySelector("#root"));

二、组件中的事件处理

1、事件绑定

(1)语法on+事件名 ={事件处理程序}比如onClick={this.handleClick};
(2)React事件采用驼峰命名法,比如onMouseEnter、onClick;
(3)函数式组件中不需要写this。

class Hello extends React.Component {
  state = {
    count: 0,
  };
  handelClick = () => {
    console.log('Hello Word')
  };
  render() {
    return (
      <>
        <p>当前值为:{this.state.count}</p>
        <button onClick={this.handelClick}>按钮</button>
      </>
    );
  }
}

2、事件处理与setState

事件对象

(1)可以通过事件处理程序的参数获取到事件对象;
(2)React 中的事件对象是 React 内部处理后的事件对象,用法与 DOM 原生的事件对象用法基本一致,例如: e.preventDefault()。

this指向

事件处理程序中的this指向的是undefined,render方法中的this指向的是当前react组件。只有事件处理程序中的this有问题。
解决方法:
(1)事件处理函数直接使用箭头函数即可;
(2)直接在标签内部写一个箭头函数,在剪头函数中调用事件处理函数(因为render中的this是没有问题的,而箭头函数沿用上层作用域中的this);
(3)使用bind改变this指向,绑定render中的this。

class Hello extends React.Component {
  state = {
    count: 0,
  };
  handelClick = () => {
    console.log('Hello Word')
  };
  render() {
    return (
      <>
        <p>当前值为:{this.state.count}</p>
        <button onClick={() => this.handelClick()}>+1</button>
      </>
    );
  }
}

setState 修改状态

语法:this.setState({ 要修改的部分数据 })

setState 是哪来的?从 Component 父类继承过来的,需要基于当前状态再做修改,不能直接修改(状态不可变概念)

class Hello extends React.Component {
  state = {
    count: 0,
  };
  handelClick = () => {
    this.setState({
      count: this.state.count + 1,
    });
  };
  render() {
    return (
      <>
        <p>当前值为:{this.state.count}</p>
        <button onClick={() => this.handelClick()}>+1</button>
      </>
    );
  }
}

三、非受控组件-Ref的使用

使用ref获取Dom

(1)调用 createRef 函数来创建一个 ref 对象
(2)ref 对象的名称(txtRef)可以是任意值
(3)current的值才是DOM对象

class Hello extends React.Component {
  txtRef=createRef()
  state = {
    msg:'mo'
  };
  handelClick = () => {
    console.log(this.txtRef.current.value);
  };
  handelChange = (e) => {
    this.setState({
      msg:e.target.value
    })
    console.log(this.state.msg);
  }
  render() {
    return (
      <>
        <button onClick={() => this.handelClick()}>获取</button>
        <input type='text' value={this.state.msg} ref={this.txtRef} onChange={this.handelChange}></input>
      </>
    );
  }
}

四、组件通讯

1、父传子

(1)父组件提供要传递的state数据;
(2)给子组件标签添加属性,值为 state 中的数据;
(3)子组件中通过 props 接收父组件中传递的数据,函数组件时props.数据,类组件为this.props.数据。

const Child = (props) => {
  return <p>姓名:{ props.name}</p>
}
class Hello extends React.Component {
  txtRef=createRef()
  state = {
    name:'张家豪'
  };
  render() {
    return (
      <>
        <Child name={this.state.name} />
      </>
    );
  }
}

2、子传父

(1)父组件提供一个回调函数(用于接收数据);
(2)将该函数作为属性的值,传递给子组件;
(3)子组件通过 props 调用回调函数;
(4)将子组件的数据作为参数传递给回调函数。

const Child = (props) => {
  console.log(props.getAge);
  function handelClick() {
    props.getAge(1);
  }
  return (
    <>
      <p>姓名:{props.name}</p>
      <button onClick={handelClick}>返老还童</button>
    </>
  );
};
class Hello extends React.Component {
  txtRef = createRef();
  state = {
    name: "张家豪",
    age: 18,
  };
  getAge = (item) => {
    this.setState({
      age: this.state.age - item,
    });
  };
  render() {
    return (
      <>
        <p>年龄:{this.state.age}</p>
        <Child name={this.state.name} getAge={this.getAge} />
      </>
    );
  }
}

3、兄弟组件通讯

将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态,然后执行父传子、子传父实现兄弟组件之间的通讯,此处不做过多赘述。

4、跨级组件通讯

(1)导入creatContext;
          import { createContext } from 'react';
(2)创建context对象,Provider提供状态,Consumer消费状态;
          const { Provider, Consumer } = createContext();
(3)使用 Provider 组件包裹整个应用,并通过 value 属性提供要共享的数据;
(4)使用 Consumer 组件接收要共享的数据,以回调函数的形式。

const { Provider, Consumer } = createContext();
const Send = () => {
  return  <Consumer>{color =>  <p>{ color }</p> }</Consumer>
};
const Child = (props) => {
  function handelClick() {
    props.getAge(1);
  }
  return (
    <>
      <p>姓名:{props.name}</p>
      <button onClick={handelClick}>返老还童</button>
      <Send />
    </>
  );
};
class Hello extends React.Component {
  txtRef = createRef();
  state = {
    name: "张家豪",
    age: 18,
  };
  getAge = (item) => {
    this.setState({
      age: this.state.age - item,
    });
  };
  render() {
    return (
      <>
        <Provider value='green'>
          <p>年龄:{this.state.age}</p>
          <Child name={this.state.name} getAge={this.getAge} />
        </Provider>
      </>
    );
  }
}

五、总结

时间关系,本次只总结了这么多,下次将会介绍props的其他用法、setState进阶、组件的生命周期以及函数组件中Hooks的使用。

诸君,我们下期再见~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值