react由于组件化,使得组件间通讯十分的重要。本文就来简单介绍一些常见的react组件间传递的内容。 我将概括为如下几种关系来详述:父组件与子组件之间,子组件与父组件之间,发布者与订阅者模式(context),兄弟组件间,redux也是一种组件管理的方法,可是redux状态管理的内容比较多,这里只作简单介绍,以后再另开一篇详述。react
react的数据流是单向的,最多见的就是经过props由父组件向子组件传值。redux
咱们作一个简单的选择商品,而后改变价格的事例。 segmentfault
class Parents extends Component {
//构造函数
constructor() {
super();
// 设置state
this.state = {
price: 0
};
}
clickGoods(e) {
//更新state
this.setState({
price: e
});
}
// 渲染
render() {
let { price } = this.state;
return (
<div>
<button onClick={this.clickGoods1.bind(this)}>goods1</button>
<button onClick={this.clickGoods2.bind(this)}>goods2</button>
// 父组件中
<Child price={price} />
</div>
);
}
}
复制代码
子组件: 子组件中使用props属性接收传递来的数据。bash
class Child extends Component {
render() {
{/*这里从props中拿到*/}
return <div> price: {this.props.price} </div>;
}
}
复制代码
codesandbox.io/s/718o454r6…app
接下来咱们反过来,让子组件向父组件通讯。 子组件向父组件通讯的基本思路是,父组件向子组件传一个函数,而后经过这个函数的回调,拿到子组件传过来的值。下面是例子,正好和上面是反的,父组件用来显示价格,子组件显示两个按钮,子组件把价格传递给父组件。ide
父组件函数
class Parents extends Component {
constructor() {
super();
this.state = {
price: 0
};
}
getItemPrice(e) {
this.setState({
price: e
});
}
render() {
return (
<div>
<div>price: {this.state.price}</div>
{/* 向子组件中传入一个函数 */}
<Child getPrice={this.getItemPrice.bind(this)} />
</div>
);
}
}
复制代码
子组件组件化
class Child extends Component {
clickGoods(e) {
// 在此函数中传入值
this.props.getPrice(e);
}
render() {
return (
<div>
<button onClick={this.clickGoods.bind(this, 100)}>goods1</button>
<button onClick={this.clickGoods.bind(this, 1000)}>goods2</button>
</div>
);
}
}
复制代码
codesandbox.io/s/718o454r6…post
React 的props都是由父组件传递给子组件的,一旦遇到孙组件,就须要一层层的传递下去。而context提供了一种组件之间通信的新的方式(16.3版本以后),能够共享一些数据,其它的组件都能从context中读取数据(相似于有个数据源,组件能够订阅这个数据源)。性能
咱们可使用createContext来建立一个context,它能够接收一个变量或者对象作为参数(当对象为参数的时候,react使用object.is()去比较,有些影响性能)。这个传入的值作为context的默认值
const PriceContext = React.createContext('price')
复制代码
这样就建立了一个Context
Provider就是用来建立数据源的。它是给全部的子组件提供数据源的跟组件。它接受一个value做为props,用来传递值,它会改变context的默认值。一个provider能够包含多个Consumer组件。若是Provider组件嵌套的话,
<PriceContext.Provider value={100}>
</PriceContext.Provider>
复制代码
Consumer表示接受数据的组件,它接受一个函数作为子元素。这个函数会接收context传递的值,返回一个react的组件。Consumer组件必须包含在Provider里面。
<PriceContext.Consumer>
{ /*这里是一个函数*/ }
{
price => <div>price:{price}</div>
}
</PriceContext.Consumer>
复制代码
在这部分咱们尝试一下从父组件直接传递到孙组件,不经过子组件(直接从A组件传值到C组件,不通过B组件)。
// 建立Context
const PriceContext = React.createContext('price')
// A组件中
class ClassA extends Component {
constructor(){
super()
this.state={
price:0
}
}
// 点击按钮事件
clickGoods(e) {
this.setState({
price:e
})
}
render(){
const { price } = this.state
return(
// Provider
// 把state里price转到Provider的value中
<PriceContext.Provider value={price}>
<button onClick={this.clickGoods.bind(this, 100)}>goods1</button>
<button onClick={this.clickGoods.bind(this, 1000)}>goods2</button>
<ClassB />
</PriceContext.Provider>
)
}
}
// 组件B
class ClassB extends Component {
// 组件B中只是引用了ClassC,没有进行传值的操做
render(){
return(
<div><span>price:</span><span><ClassC /></span></div>
)
}
}
// 组件C
class ClassC extends Component {
render(){
return(
// Consumer,注意Consumer的下面要包含一个函数
<PriceContext.Consumer>
{
price=><span>{price}</span>
}
</PriceContext.Consumer>
)
}
}
复制代码
一个react app是由不少react组件组成的,有的组件之间是有嵌套关系的,能够造成一条“组件链”。Context能够当作组件的“做用域”[3]。一个根组件,它定义了一个context,它的组件链上的组件均可以访问到provider中定义的变量或对象,以下图所示,这就比较像‘做用域’的概念。context在一些简单的场景下能够替代部分redux的功能。
兄弟间组件通讯,通常的思路就是找一个相同的父组件,这时候既能够用props传递数据,也能够用context的方式来传递数据。 固然也能够用一些全局的机制去实现通讯,好比redux等。
本文主要介绍了3种通讯的关系父组件与子组件之间,子组件与父组件之间,发布者与订阅者模式(context),简述了兄弟组件间的通讯。主要是介绍两种方式,利用props属性和Context。也介绍了一些context的理解。
[1] segmentfault.com/a/119000001…