React的跨级组件通信

版权声明:欢迎转载,转载请注明原始出处 https://blog.csdn.net/xiaomingelv/article/details/85331941

我们知道,react中父子组件之间的通信,父组件和子组件通信,可以通过props向子组件传递参数,子组件和父组件通信,则可以通过调用props传入的回调函数来向父组件传递参数

那么问题来了,如果是跨级组件之间的通信,如果通过props一层一层往下传,不仅逻辑会变得很不清晰,代码也会变得不好维护,这个时候,我们需要使用到react中的context来解决这个问题

首先我们来看一段代码

class Item extends Component {
    static contextTypes = {
        color: React.PropTypes.string,
    };

    render() {
        const {value} = this.props;
        return (
            <li style={{background: this.context.color}}>
                <span>{value}</span>
            </li>
        );
    }
}


class List extends Component {
    static childContextTypes = {
        color: React.PropTypes.string,
    };

    getChildContext() {
        return {
            color: 'red',
        };
    }

    render() {
        const {list} = [{id:'1',text:1},{id:'1',text:2},{id:'1',text:3}]
        return (
            <div>
                <ul>
                    {list.map((entry, index) => (
                        <Item key={entry.id} value={entry.text}/>
                    ))}
                </ul>
            </div>
        );
    }
}

以上是一个如何通过context进行通信的示例,我们可以看到Item组件接收的color参数并不是通过props进行传递的,而是通过this.context获取的。

要实现这个功能,首先我们需要在父组件中显式的定义静态属性childContextTypes,并在属性中声明要传入的参数的类型,同时在父组件中实现getChildContext方法,这个方法的返回值,将会传入到父组件下面的任何一个子组件的context中,这样一来,父组件的所有级别的子组件都将可以跨级别获取到父组件的参数。

而当子组件需要使用父级及父级以上级别的组件传入的参数时,需要在子组件中显示定义静态属性contextTypes,并在属性中声明要使用的参数的类型,这样,子组件就可以在context中获取到跨级别传入的参数了。

这种方式在react-router中得到了应用,我们可以发现,在组件中写下了以下代码之后

static contextTypes = {
    router: React.PropTypes.object.isRequired
}

我们就可以使用this.context.router.push等方法,进行路由跳转了,就是这个道理。

新的api出现

光阴似箭岁月如梭,来到了2018年,react发布了16.3版本,提供了新的context api,看上去更加的简洁,并且用了生产者消费者模式,看看下面的示例代码

const {Provider, Consumer} = React.createContext({
    color: 'white'
});


class Item extends Component {
    static contextTypes = {
        color: React.PropTypes.string,
    };

    render() {
        const {value} = this.props;
        return (
            <Consumer>
                {context => (
                    <li style={{background: context.color}}>
                        <span>{value}</span>
                    </li>
                )}
            </Consumer>
        );
    }
}


class List extends Component {

    render() {
        const {list} = [{id: '1', text: 1}, {id: '1', text: 2}, {id: '1', text: 3}]
        return (
            <Provider value={{color: 'green'}}>
                <div>
                    <ul>
                        {list.map((entry, index) => (
                            <Item key={entry.id} value={entry.text}/>
                        ))}
                    </ul>
                </div>
            </Provider>
        );
    }
}

以上代码改写自前面的代码片段,用新的api重新实现,我们可以看到,上面的代码通过React.createContext创建出一个上下文:Context对象,然后这个Context对象又包含两个属性,一个叫Provider,另一个叫Consumer,这两个属性都是纯种的React组件。

之后我们只需要和上面代码片段一样,在父组件中运用Provider,在子组件中运用Consumer即可,Provider中通过value属性可以向Consumer传递参数,而Consumer的子组件则是一个函数,在这个子组件中定义一个函数,Consumer会向它传递一个context,这个context来自于Provider,达到通信的目的

和旧的api一样,这种传递参数的方式,支持跨多个级别的组件进行通信,可以用于从父组件向父组件一下的所有组件传递参数

没有更多推荐了,返回首页