react组件通信那些事儿

react

子组件向父组件通信:父组件给子组件传递props(callback函数),该函数必须将this绑定到父组件。子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中,实现子组件向父组件的通信。

原文链接:http://www.cnblogs.com/camille666/p/react_compoment_chat.html

父组件是调用组件的组件。
现在看来,感觉父组件就是一个壳子,定义好壳子里面会有什么,而子组件是一个具体的实现,说明,会用到什么东西,如果有这些东西,会进行什么操作。总之,父组件是材料,有水和泥,子组件告诉你,怎么制作水泥。
父组件给子组件输入什么,子组件就是什么。不同的父组件调用,或许可以呈现不同的输出,前提是在子组件里面要定义不同的接口,属性方法,供不同的父组件使用。

父子:Parent与Child_1、Child_2、Child_1_1、Child_1_2、Child_2_1

兄弟:Child_1与Child_2、Child_1_1与Child_2、etc

 

一、简单通信

1、父组件向子组件通信(props)

父组件给子组件传递props(属性),实现父组件向子组件的通信。

class Parent extends React.Component {

state = {

msg: 'start'

};

componentDidMount() {

setTimeout(() => {

this.setState({

msg: 'end'

});

}, 1000);

}

render() {

return <Child_1 msg={this.state.msg} />;

}

}

class Child_1 extends React.Component {

render() {

return <p>{this.props.msg}</p>;

}

}

A、重点

发送方:<Child_1 msg="父组件向子组件通信" />

接收方:<p>{this.props.msg}</p>

B、插播

ES6明确规定,class里面只有静态方法,没有静态属性。自从有了静态属性的提案,可以在class里写实例属性和静态属性。之前都是在constructor里面初始化状态,现在可以直接写状态作为class的实例属性。

2、子组件向父组件通信(回调函数)

父组件给子组件传递props(callback函数),子组件调用该函数,将子组件想要传递的信息,作为参数,传递到父组件的作用域中,实现子组件向父组件的通信。

class Parent extends React.Component {

state = {

msg: 'start'

};

fMsg(msg) {

this.setState({

msg

});

}

render() {

return (

<div>

<p>child msg: {this.state.msg}</p>

<Child_1 transferMsg={msg => this.fMsg(msg)} />

</div>

);

}

}

class Child_1 extends React.Component {

componentDidMount() {

setTimeout(() => {

this.props.transferMsg('end');

}, 1000);

}

render() {

return (

<div>

<p>child_1 component</p>

</div>

);

}

}

发送方:<Child_1 transferMsg={(msg) => {console.log(msg);}} />

接收方:<a onClick={this.props.transferMsg('子组件向父组件通信')}>子组件发送</a>

3、兄弟组件通信

A、状态提升

兄弟组件不能直接通过props进行消息传递,但是兄弟组件有相同的父元素,因此可以将需要传递的数据挂载在父组件中,由两个兄弟组件共享。

由Child_1向Child_2进行通讯,我们可以先通过Child_1向Parent进行通讯,再由Parent向Child_2进行通讯。

class Parent extends React.Component {

state = {

msg: 'start'

};

fMsg(msg) {

this.setState({

msg

});

}

componentDidUpdate() {

console.log('Parent update');

}

render() {

return (

<div>

<Child_1 transferMsg={msg => this.fMsg(msg)} />

<Child_2 msg={this.state.msg} />

</div>

);

}

}

class Child_1 extends React.Component {

componentDidMount() {

setTimeout(() => {

this.props.transferMsg('end');

}, 1000);

}

componentDidUpdate() {

console.log('Child_1 update');

}

render() {

return (

<div>

<p>child_1 component</p>

</div>

)

}

}

class Child_2 extends React.Component {

componentDidUpdate() {

console.log('Child_2 update');

}

render() {

return (

<div>

<p>child_2 component: {this.props.msg}</p>

</div>

)

}

}

这种方式耦合比较严重,父组件承担了本来与自己无关的功能。每次进行消息传递都会触发父组件和子组件的生命周期,如果消息传递比较频繁,会造成很大的浪费。

B、观察者模式

import eventProxy from '../eventProxy';

class Parent extends React.Component {

render() {

return (

<div>

<Child_1 />

<Child_2 />

</div>

);

}

}

class Child_1 extends React.Component {

componentDidMount() {

setTimeout(() => {

// 发布者,发布msg事件

eventProxy.trigger('msg', 'end');

}, 1000);

}

}

class Child_2 extends React.Component {

state = {

msg: 'start'

};

componentDidMount() {

// 订阅者,监听msg事件

eventProxy.on('msg', (msg) => {

this.setState({

msg

});

});

}

render() {

return (

<div>

<p>child_2 component: {this.state.msg}</p>

</div>

)

}

}

4、跨级组件通信

如果父组件与子组件之间不止一个层级,如Parent与Child_1_1这样的关系,该怎么通信呢?

A、层层传递

可通过...运算符(Object 剩余和展开属性),将父组件的信息,以更简洁的方式传递给更深层级的子组件。

// 通过...运算符向Child_1_1传递Parent组件的信息

class Child_1 extends React.Component {

render() {

return (

<div>

<p>{this.props.msg}</p>

<Child_1_1 {...this.props} />

</div>

)

}

}

class Child_1_1 extends React.Component {

render() {

return <p>{this.props.msg}</p>;

}

}

B、context对象

context相当于一个全局变量,是一个大容器,我们可以把要通信的内容放在这个容器中,这样一来,不管嵌套有多深,都可以随意取用。

如果是父组件向子组件单向通信,可以使用变量,如果子组件想向父组件通信,同样可以由父组件提供一个回调函数,供子组件调用,回传参数。

上级组件要声明自己支持context,指定组件的childContextTypes属性,并提供一个getChildContext函数来返回初始的context对象;

子组件要声明自己需要使用context,指定组件的contextTypes属性,就可以通过this.context访问这个共同的环境对象。

class Parent extends React.Component {

getChildContext() {

return {

color: 'red',

cbFun: this.fCallback.bind(this)

};

}

fCallback(msg) {

console.log(msg);

}

render() {

return <Child_1 />;

}

}

Parent.childContextTypes = {

color: PropTypes.string,

cbFun: PropTypes.func

}

class Child_1 extends React.Component {

render() {

return <Child_1_1 />;

}

}

class Child_1_1 extends React.Component {

static contextTypes = {

color: PropTypes.string,

cbFun: PropTypes.func

}

render() {

const styles = { color: this.context.color };

const cb = (msg) => {

return () => {

this.context.cbFun(msg);

}

}

return (

<button style={styles} onClick={cb('子组件向父组件传数据。')}>点击</button>

)

}

}

我们不应该也不能直接改变context对象中的属性,要想改变context对象,只有让其和父组件的state或者props进行关联,在父组件的state或props变化时,会自动调用getChildContext方法,返回新的context对象,而后子组件进行相应的渲染。

class Parent extends React.Component {

constructor(props) {

super(props);

this.state = {

color: "red"

}

}

getChildContext() {

return {

color: this.state.color,

cbFun: this.fCallback.bind(this)

};

}

fCallback(color) {

this.setState({color});

}

render() {

return <Child_1 />;

}

}

Parent.childContextTypes = {

color: PropTypes.string,

cbFun: PropTypes.func

}

class Child_1 extends React.Component {

render() {

return <Child_1_1 />;

}

}

class Child_1_1 extends React.Component {

static contextTypes = {

color: PropTypes.string,

cbFun: PropTypes.func

}

render() {

const styles = { color: this.context.color };

const cb = (msg) => {

return () => {

this.context.cbFun(msg);

}

}

return (

<button style={styles} onClick={cb('blue')}>点击</button>

)

}

}


以上是 react组件通信那些事儿 的全部内容, 来源链接: utcz.com/z/383387.html

回到顶部