React从0开始(四):基础组件间通信(上)

309 阅读2分钟

这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

一、PropsState

PropsProps可以认为是父组件传给子组件的参数,这个参数对于子组件来说是只读的(纯净的),子组件无法直接对其进行修改。但是,子组件可以通过触发父组件从Props中传来的函数对父组件的State进行修改(则有可能会修改到传进来的Props

StateState指的是当前组件的一个状态,组件可以通过方法来对当前的状态进行修改,从而触发页面的重新渲染,可以通过this.setState对当前状态进行修改,但是要注意这一操作是异步的

二、单项数据流之Props

父-子通信

常用方法:Props,通过Props传值让子组件发生变化 代码如下:

//父组件
constructor(props){
    super(props);
    this.state = {
        content:"父组件传给子组件的内容"
    }
}
render() {
    return (
        <div>
            <Children change={this.changeContent} content={this.state.content} />
            <button onClick={ ()=>{ this.setState({ content:"父组件内容发生了改变" }) } }>点击改变传值内容</button>
        </div>
    )
}
changeContent(content) {
    this.setState({
        content:content
    })
}
//子组件
render() {
    return (
        <div>{this.props.content}</div>
    )
}

可得到效果如下:

image.png

image.png

子-父通信

原理:父组件通过Props传入可以改变自己State的函数,随后由子组件触发该函数,该函数修改父组件State达到子-父组件通信的目的,代码如下:

//父组件
render() {
    return (
        <div>
            <div>{this.state.content}</div>
            <Children change={this.changeContent} content={this.state.content} />
        </div>
    )
}
changeContent = (content) => {
    this.setState({
        content:content
    })
}
//子组件
render() {
    return (
        <div>
            <button onClick={this.changeParent}>修改父组件内容</button>
        </div>
    )
}
changeParent = () => {
    this.props.change("父组件内容被修改了");
}

可得以下效果:

image.png

image.png

兄弟组件通信

原理:两个兄弟组件A、B之间进行通信,可以理解为A通过Props调用父组件的函数修改State从而更新B的Props

//父组件
constructor(props) {
    super(props)
    this.state = {
        content:"B组件初始内容"
    }
}
render() {
    return (
        <div>
            <NewChildren toB={this.state.content} />
            <Children change={this.changeContent} content={this.state.content} />
        </div>
    )
}
changeContent = (content) => {
    this.setState({
        content:content
    })
}
//兄弟A
render() {
    return (
        <div>
            <button onClick={this.changeParent}>兄弟A</button>
        </div>
    )
}
changeParent = () => {
    this.props.change("兄弟A修改兄弟B(组件间通信)");
}
//兄弟B
render() {
    return (
        <div>
            <div>兄弟B:{this.props.toB}</div>
        </div>
    )
}

可得以下效果:

image.png

image.png

三、发布订阅模式

发布订阅模式也是组件间通信的老演员了,我们在这里实现以下发布订阅模式并且在React里尝试使用:

  1. 发布订阅模式的实现
class EventEmitter {

    constructor() {
        this.eventMap = {}
    }

    on(name,handle) {
        if(!(handle instanceof Function)){
            return new Error('请传一个函数');
        }
        if(this.eventMap[name]){
            this.eventMap[name].push(handle);
        }else{
            this.eventMap[name] = [];
            this.eventMap[name].push(handle);
        }
    }

    emit(name,params) {
        if(this.eventMap[name]){
            this.eventMap[name].forEach((handle,index)=>{
                handle(params);
            })
        }
    }

    off(name,handle) {
        this.eventMap[name].splice(this.eventMap[name].indexOf(handle),1)
    }
}
export default new EventEmitter()
  1. 发布订阅模式在React中的使用
//父组件
constructor(props) {
    super(props)
    this.state = {
        content:"发布订阅模式"
    }
}
render() {
    return (
        <div>
            <button onClick={this.changeContent}>添加监听事件</button>
            <Children content={this.state.content} />
        </div>
    )
}
changeContent = () => {
    EventEmitter.on("change",(content)=>{
        this.setState({
            content:content
        })
    })
}
//子组件
render() {
    return (
        <div>
            <div>{this.props.content}</div>
            <button onClick={this.changeParent}>发布订阅触发</button>
        </div>
    )
}
changeParent = () => {
    EventEmitter.emit("change","发布订阅模式生效");
}

可得以下效果:

image.png

点击监听事件添加以后即可进行触发

image.png