react--事件--组件通信

事件处理

绑定事件

  • 采用on+事件名的方式来绑定一个事件
  • 这里和原生的事件是有区别的,原生的事件全是小写如onclick,React中的事件是驼峰如onClick
  • React的事件并不是原生事件,而是合成事件

事件handler的写法

  • 直接在render里写行内的箭头函数(不推荐)
    看着不爽,污染了html结构
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'
class Event extends Component{
    constructor(){
        super()
        this.state={
            flag:true
        }
    }//定义类状态

    render () {
    return (
      <Fragment>//可省略一个外层div
        <button onClick = { () => { this.setState({
          flag: !this.state.flag
        })} }> 切换 </button>
        <h3>直接用箭头函数在render函数中书写 </h3>
       { this.state.flag && <img src = "/img/img (1).jpg"/> }
      </Fragment>
    )
  }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)
  • 在组件内使用一个箭头函数来定义一个方法(推荐)
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'

class Event extends Component{
    constructor(){
        super()
        this.state={
            flag:true
        }
    }
    change=()=>{
        this.setState({
            flag:!this.state.flag
        })
    }
    render(){
        return(
            <Fragment>
                <button onClick={this.change}>切换</button>
                <h3>在组件内使用箭头函数来定义方法</h3>
                {this.state.flag&&<img src=""/>}
            </Fragment>
        )
    }
}
ReactDom.render(
    <Event/>,
    document.getElementById('root')
)
  • 直接在组件内定义一个非箭头函数的方法,然后在render里面直接使用 onClick=
    {this.handleClick.bind(this)}(不推荐)
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'

class Event extends Component{

    constructor(){
        super()
        this.state={
            flag:true
        }
    }

    change(){
        //直接被下方调用,这里的this指向会丢失,要进行绑定
        this.setState({
            flag:!this.state.flag
        })
    }
    render(){
        return(
            <Fragment>
                <button onClick={this.change.bind(this)}>切换</button>
                <h3>在组件内定义非箭头函数的方法,在render里面直接使用并使用bind改变this指向</h3>
                {this.state.flag&&<img src=""/>}
            </Fragment>
        )
    }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)
  • 直接在组件里面定义一个非箭头函数的方法,然后在constructor里面bind(this)
import React,{Component,Fragment}from 'react'
import ReactDom from 'react-dom'

class Event extends Component{
    constructor(){
        super()
        this.state={
            flag:true
        }
    this.change=this.change.bind(this)
    }
    change(){
        this.setState({
            flag:!this.state.flag
        })
    }

    render(){
        return(
            <Fragment>
            <button onClick={this.change}>切换</button>
            <h3>组件内定义非箭头函数方法,构造函数绑定this</h3>
            {this.state.flag&&<img src=""/>}
            </Fragment>
        )
    }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)

Event 对象

  • 和普通浏览器一样,事件handler会被自动传入一个event对象,这个对象和普通的浏览器event对象所包含的方法和属性基本一致。不同的是React中的event对象不是浏览器所提供的,而是它自己内部所构建的,它同样具有event.stopPropagation、event.preventDefault这种常用的方法。
    事件对象中的值很多都是null,但是可以正常使用。
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'

class Event extends Component{

    constructor(){
        super()
        this.state={
            flag:true
        }
    }

    change=(e)=>{
        console.log(e)//React内部所构建,具有常用方法,可正常使用。
        console.log(e.clientX)
        this.setState({
            flag:!this.state.flag
        })
    }
    render(){
        return(
            <Fragment>
                <button onClick={this.change}>切换</button>
                <h3>event对象</h3>
                {this.state.flag&&<img src=""/>}
            </Fragment>
        )
    }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)

事件的参数传递

  • 在render里调用方法的地方外面包一层箭头函数(比较推荐)
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'

class Event extends Component{

    constructor(){
        super()
        this.state={
            flag:true,
            msg:''
        }
    }

    change=(val)=>{
        this.setState({
            flag:!this.state.flag,
            msg:val
        })
    }

    render(){
        return(
            <Fragment>
            //这里调用方法时如果直接加个括号加个参数,会立即调用,造成死循环,所以套一个箭头函数
                <button onClick={()=>{this.change(12345)}}>切换图片与文字</button>
                <h3>事件传参-方法调用外包一层箭头函数</h3>
                <p>msg:{this.state.msg}</p>
                {this.state.flag&&<img src=""/>}
            </Fragment>
        )
    }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)
  • 在render里通过this.handleEvent.bind(this, 参数)这样的方式来传递,写法如下
import React,{Component,Fragment}  from 'react'
import ReactDom from 'react-dom'

class Event extends Component{

    constructor(){
        super()
        this.state={
            flag:true,
            msg:''
        }
    }
    change=(val)=>{
        this.setState({
            flag:!this.state.flag,
            msg:val
        })
    }

    render(){
        return(
            <Fragment>
                //不会立即调用,并携带参数
                <button onClick={this.change.bind(this,12345)}>切换图片和文字</button>
                <h3>通过this.handleEvent.bind(this,参数)</h3>
                <p>msg:{this.state.msg}</p>
                {this.state.flag&&<img src=""/>}
            </Fragment>
        )
    }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)
  • 比较推荐的是做一个子组件,在父组件中定义方法,通过props传递到子组件中,然后子组件通过this.props.method来调用
import React,{Component} from 'react'
import ReactDom from 'react-dom' 
//创建子组件
class Son extends Component{
    render(){
        return(
            <div>
                //子组件通过this.props.method来调用
                //传参时注意立即调用问题,套个箭头函数
                <button onClick={()=>{this.props.kick(111000)}}>kick</button>
            </div>
        )
    }
}
//创建父组件
class Father extends Component{
    constructor(){
        super()
        this.state={
            kick:'踢'
        }
    }
    //在父组件中定义方法
    kick=(val)=>{
        this.setState({
            kick:'踢了好几脚'+ val
        })
    }
    render(){
         return(
             <div>//将父组件定义的方法绑定在子组件上
                <Son kick={this.kick} />
                <p>{this.state.kick}</p>
             </div>
         )
    }
}

ReactDom.render(
     <Father/>,
    document.getElementById('root')
)

处理用户输入

import React,{Component,Fragment}from 'react'
import ReactDom from 'react_dom'

class Event extends Component{

    constructor(){
        super()
        this.state={
            msg:''
        }
    }
    changeMsg=(e)=>{
        this.setState({
            msg:e.target.value
            //事件对象
            //e.target事件源
        })
    }

    render(){
        return(
            <Fragment>
            <input type="text" onInput={this.changeMsg}/>
            <p>展示数据:{this.state.msg}</p>
            </Fragment>
        )
    }
}
ReactDom.render(
    <Event/>,
    document.getElementById('root')
)
  • ref绑定:普通绑定
import React,{Component,Fragment}from 'react'
import ReactDom from 'react_dom'

class Event extends Component{

    constructor(){
        super()
        this.state={
            msg:''
        }
    }

    changeMsg=()=>{
        this.setState({
            msg:this.refs.user.value
        })
    }
    render(){
        return(
            <Fragment>
            //在标签绑定ref属性,值为user
            <input type="text" onInput={this.changeMsg}   ref="user"/>
            <p>展示数据:{this.state.msg}</p>
            </Fragment>
        )
    }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)
  • ref绑定:通过函数形式绑定

import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'

class Event extends Component{

    constructor(){
        super()
        this.state={
            msg:''
        }
    }

    changeMsg=()=>{
        this.setState({
            msg:this.user.value
        })
    }
    render(){
        return(
            <Fragment>
            <input  onInput={this.changeMsg} type="text" ref={el=>this.user=el}/>
            <p>展示数据:{this.state.msg}</p>
            </Fragment>
        )
    }
}

ReactDom.render(
    <Event/>,
    document.getElementById('root')
)

组件通信

父子组件通信

  • 无论父组件传递的是props还是state,子组件都是用props接收
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'

//son 组件
class Son extends Component{
  render () {
    return (
      <Fragment>
        <h3> 这里是Son组件 </h3>
        <p> 父亲传递过来的数据:{this.props.name}</p>
      </Fragment>
    )
  }
}

//Father zujian

class Father extends Component{
    constructor(){
        super()
        this.state={
            name:"二狗子"
        }
    }
    render(){
        return(
            <Fragment>
                <h3>这是Father组件</h3>
                <Son {...this.state} />
            </Fragment>
        )
    }
}
ReactDom.render(
    <Father/>,
    document.getElementById('root')
)

子父组件通信

  • 父组件传递方法给子组件,子组件调用父组件传递过来的方法
  • 注意:自己的状态自己更改
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'
//子组件
class Son extends Component{
  render () {
    return (
      <Fragment>
        <h3> 这里是Son组件 </h3>
        <button onClick = { () => { this.props.change( '张三' ) }}> 改名 </button>
        <p> 父亲传递过来的数据: { this.props.name } </p>
      </Fragment>
    )
  }
}
//父组件
class Father extends Component{
  constructor () {
    super()
    this.state = {
      name: '二狗子'
    }
  }

  change = ( val ) => {
    this.setState({
      name: val
    })
  }

  render () {
    return (
      <Fragment>
        <h3> 这里是Father组件 </h3>
        <hr/>
        <Son change = { this.change }/>
        <p> name: { this.state.name } </p>
      </Fragment>
    )
  }
}

ReactDom.render(
    <Father/>,
    document.getElementById('root')
)

非父子组件通信 ref函数

import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'
//girl
class Girl extends Component{
  render () {
    return (
      <Fragment>
        // 接收父组件传过来的方法,并调用
        <button onClick = { this.props.kick }> 揍弟弟 </button>
        <h3> 这里是Girl组件 </h3>
      </Fragment>
    )
  }
}
//son
class Son extends Component{

  constructor () {
    super()
    this.state = {
      flag: false
    }
  }
    //定义方法
  change = () => {
    this.setState({
      flag: !this.state.flag
    })
  }

  render () {
    return (
      <Fragment>
        <h3> 这里是Son组件 </h3>
        { this.state.flag && <p> o(╥﹏╥)o  o(╥﹏╥)o  o(╥﹏╥)o  o(╥﹏╥)o </p> }
      </Fragment>
    )
  }
}
//father
class Father extends Component{
  constructor () {
    super()
  }

  kick = () => {
    console.log( this )
    this.son.change()
  }

  render () {
    return (
      <Fragment>
        <h3> 这里是Father组件 </h3>
        <hr/>
        <Son ref = { el => this.son = el}/>
        <Girl ref = { el => this.girl = el }  kick = { this.kick }/>
      </Fragment>
    )
  }
}

ReactDom.render(
    <Father/>,
    document.getElementById('root')
)

跨组件通信

  • context 创建上下文React.createContext() 使用上下文包裹目标组件的父组件
 <MyContext.Provider value = { this.state.xxx}>
    	<Father></Father>
    </MyContext.Provider>
  • 在目标组件中先定义一个静态属性 static contextType = MyContext
  • 通过 this.context来使用数据
import React,{Component,Fragment} from 'react'
import ReactDom from 'react-dom'

const MyContext = React.createContext()

//儿子组件目标组件

class Son extends Component{

  constructor () {
    super()
  }

  static contextType = MyContext
  
  render () {
    console.log( this )
    return (
      <Fragment>
        <h3> 这里是Son组件 </h3>
        <p> grandFather 组件给我的数据  { this.context } </p>
      </Fragment>
    )
  }
}

//父组件

class Father extends Component{
  constructor () {
    super()
  }

 
  render () {
    return (
      <Fragment>
        <h3> 这里是Father组件 </h3>
        <Son/>
      </Fragment>
    )
  }
}

//祖父组件
class GrandFather extends Component{

  constructor () {
    super()
    this.state = {
      name: "mingliang"
    }
  }

  render () {
    return (
      <Fragment>
        <h3> 这里是爷爷组件 </h3>
        <hr/>
        <MyContext.Provider value = { this.state.name }>
          <Father/>
        </MyContext.Provider>
      </Fragment>
    )
  }
}
ReactDom.render(
    <GrandFather/>,
    document.getElementById('root')
)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值