React入门系列文章:7. 事件触发与组件通讯

1. 事件触发

React采用跟原生相同名字驼峰写法props来定义触发类型。
比如onclick在React中使用onClick来定义触发的事件。

<div 
    onClick={(e)=>{
        console.log('onclick')
        console.log(e)
    }}
>点击触发事件</div>

当用户点击之后,浏览器会在控制台输出

onclick
event:{}

React为事件响应做了处理,在所有的浏览器中,event是统一的、拥有一致性。

如果你非常需要使用原生对象,那么可以通过event.nativeEvent来访问浏览器原生的事件方法。

在React中,绑定事件有很多种方式,但是我推荐使用=>箭头方法直接指定事件处理。这种方式集合众家所长。

2. 组件间通讯

组件通讯可以用React的方式,也可以采取Redux数据驱动通讯的方式来进行。我们来简单的讲述一下React的实现。

2.1 父向子通讯

import React from 'react'

class Subchildren extends React.Component{
    render () {
        return <div>{this.props.text}</div>
    }
}


export default FatherChildren extends React.Component{
    static state = {
        count:0
    }
    
    handleAdd = () => {
        this.setState({count:this.state.count++})
    }

    render () {
        return <div>
            <Subchildren text={this.state.count}/>
            <button onClick={this.handleAdd}>喜加1</button>
        </div>
    }
}

这个时候,你点击按钮 喜加1 就会发现 子组件的内容会随着父组件中state.count的值变化而变化。

这是一种数据流向通讯。因为只需要向子组件传递消息即可。

2.2 子向父通讯

React中并没有像Vue一样的监听子组件$on$emmit的功能,但是不妨碍我们将事件传入给子组件,由子组件通过事件将信息递交回父组件。

import React from 'react'

class Subchildren extends React.Component{
    render () {
        return <> <div>{this.props.text}</div>
        <button
            onClick={()=>{
                    this.props.onClick(0)
                }
            }
        >重置为0</button>
        </>
    }
}


export default FatherChildren extends React.Component{
    static state = {
        count:0
    }
    
    handleAdd = () => {
        this.setState({count:this.state.count++})
    }
    
    handlePostMessage = (count) => {
        this.setState({count})
    }

    render () {
        return <div>
            <Subchildren
                onClick={this.handlePostMessage}
                text={this.state.count}/>
            <button
                onClick={this.handleAdd}
            >喜加1</button>
        </div>
    }
}

点击重置为0子组件并没有去做重置操作,而是委托给父组件传递下来的事件进行操作。这样父组件就知道了子组件想要将数据修改为0了。

2.3 兄弟组件通讯

兄弟组件通讯其实就是:父子组件通讯+子父组件通讯的混合体。

先通过子向父通讯,父组件接收到数据之后再写入到兄弟组件上去。

import React from 'react'

class Subchildren extends React.Component{
    render () {
        return <> <div>{this.props.text}</div>
        <button
            onClick={()=>{
                    this.props.onClick(100)
                }
            }
        >重置为0</button>
        </>
    }
}

class Subchildren2 extends React.Component{
    render () {
        return <> <div>{this.props.text}</div>
        </>
    }
}


export default FatherChildren extends React.Component{
    static state = {
        count:0,
        count2:0
    }
    
    handleAdd = () => {
        this.setState({count:this.state.count++})
    }
    
    handlePostMessage = (count) => {
        this.setState({count2:count})
    }

    render () {
        return <div>
            <Subchildren
                onClick={this.handlePostMessage}
                text={this.state.count}/>
            <Subchildren2 text={this.state.count2} />
            <button
                onClick={this.handleAdd}
            >喜加1</button>
        </div>
    }
}

点击重置为0,你会发现Subchildren2组件显示数据的值为100。这样,兄弟组件就能相互通讯了。他们是基于父组件进行的。

2.4 跨组件通讯

2.4.1 发布订阅模式

跨组件通讯,也就是多个组件在不同的容器内组成,但是又相互有数据关系依赖这样的情况下,可以再顶层自己设计一个发布/订阅的方法。

这里不过多阐述。

2.4.2 this.context

这个方法其实就是兄弟组件通讯的原理。因为React会从root层注册一个context,而每个组件都会将context注册进来。

也就是说,所有的组件全局依赖一个顶层root的 context`。

redux也是基于这个模式设计的。

import React from 'react'

class Subchildren extends React.Component{
    render () {
        return <> <div>{this.props.text}</div>
        <button
            onClick={()=>{
                    this.context.handleAdd()
                }
            }
        >加1加1加1</button>
        </>
    }
}

class Subchildren2 extends React.Component{
    render () {
        return <> <div>{this.context.value}</div>
        </>
    }
}


export default FatherChildren extends React.Component{
    static state = {
        count:0,
        count2:0
    }
    
    handleAdd = () => {
        this.setState({count:this.state.count++})
    }
    getChildContext() {
        return {
            value: this.state.count,
            handleAdd: this.handleAdd
        }
    }
    handlePostMessage = (count) => {
        this.setState({count2:count})
    }

    render () {
        return <div>
            <Subchildren
                onClick={this.handlePostMessage}
                text={this.state.count}/>
            <Subchildren2 text={this.state.count2} />
            <button
                onClick={this.handleAdd}
            >喜加1</button>
        </div>
    }
}

主要需要注意父组件的getChildContext,与子组件中的this.context

摄影爱好者,全栈工程师,游戏玩家,积木苦手,超穷手办收藏爱好者

发表评论