React中父子组件通信详解
作者:公众号_前端每日技巧
父组件向子组件通信
在父组件中,为子组件添加属性数据,即可实现父组件向子组件通信。传递的数据可以分成两类
子组件是作为属性来接收这些数据的
第一类就是数据:变量,对象,属性数据,状态数据等等
这些数据发生改变,子组件接收的属性数据就发生了改变。
第二类就是方法:父组件可以向子组件传递属性方法,子组件接收方法,并可以在组件内执行,有两种执行方式
注意:父组件传给子组件的方法是不能执行的,执行了相当于将方法的返回值传递给子组件。
第一种 作为事件回调函数执行
参数默认就是事件对象
this默认指向undefined,因此我们要改变this指向
如果在子组件中改变,
this指向子组件
bind方式传递的参数在事件对象之前
如果在父组件中改变(工作中常用
)
this指向父组件了
此时子组件不论如何绑定,都指向父组件
bind方式传递的参数会在子组件传递的参数之前
参数顺序:父组件参数,子组件参数,事件对象
第二种 在子组件方法中执行
默认没有参数,使用什么可以传递什么
this默认指向子组件属性对象(this.props)
此时我们要在父组件中绑定this,就指向了父组件
我们既可以访问父组件实例化对象,也可以访问子组件实例化对象,
我们既可以在子组件中传递参数,也可以在父组件中传递参数
有一种简写方式(工作中常用
)
直接在事件回调函数中,定义箭头函数,并执行父组件方法:
// 定义父组件slider class Slider extends Component { // 构造函数 constructor(props) { super(props); // 初始化状态 this.state = { title: '返回顶部' } } // 父组件方法 parentMethod() { console.log(this, arguments) } render() { return ( <div className="slider"> {/*字符串*/} {/*<GoTop text="网址导航"></GoTop>*/} {/*属性数据*/} {/*<GoTop text={this.props.title}></GoTop>*/} {/*状态数据*/} {/*<GoTop text={this.state.title}></GoTop>*/} {/*传递方法*/} <GoTop text={this.state.title} method={this.parentMethod.bind(this, 200, 'parent')}></GoTop> {/*<GoTop text={this.state.title} method={this.parentMethod}></GoTop>*/} </div> ) } } // 定义组件 class GoTop extends Component { // 定义方法 childMethod(e) { // 执行父组件方法 this.props.method(200, e); } // 4 渲染虚拟DOM render() { // console.log(this.props) // 绑定事件 // return <span onClick={this.props.method.bind(this, 100, 'child')}>{this.props.text}</span> // 在子组件方法中执行 // return <span onClick={this.childMethod.bind(this)}>{this.props.text}</span> // 简便写法 return <span onClick={e => this.props.method(e)}>{this.props.text}</span> } }
存在期
组件创建完成,一旦属性数据或者状态数据发生改变,组件就会进入存在期,共分五个阶段
第一个阶段 组件即将接收新的属性数据
componnetWillReceiveProps方法
第一个参数表示新的
属性数据
组件实例化对象上的是旧的属性数据
数据还没有更新,
只有当属性数据发生改变,才会执行该方法,状态数据改变不会执行
,直接进入第二个阶段
作用:用属性数据去更新状态数据,实现数据由外部流入内部
第二个阶段 组件是否应该更新
shouldComponentUpdate方法
第一个参数表示新的
属性数据
第二个参数表示新的
状态数据
组件实例化对象上的是旧的属性数据
组件实例化对象上的是旧的状态数据
必须有返回值,表示是否可以更新
true 可以更新
false 不能更新
工作中,我们常常比较
参数中的属性数据是否与组件实例化对象中属性数据是否不相等,或者
参数中的状态数据是否与组件实例化对象中状态数据是否不相等
作用:启动更新优化的作用,常常在高频事件中使用。(类似节流作用)
第三个阶段 组件即将更新
componentWillUpdate方法:
- 第一个参数表示
新的
属性数据 - 第二个参数表示
新的
状态数据
组件实例化对象上的是旧的属性数据
组件实例化对象上的是旧的状态数据
说明此时数据仍然没有更新,当该方法执行完毕,数据才会更新
作用:更新插件,预处理数据等等,
注意:不要在第二个阶段和第三个阶段去更新属性数据以及装填数据
第四个阶段 组件渲染视图
render 方法
没有参数,但是此时数据已经更新了
- 组件实例化对象上的是
新的
属性数据 - 组件实例化对象上的是
新的
状态数据
所以我们在渲染虚拟DOM的时候,可以使用这些新的数据了
此时虚拟DOM还没有更新,方法执行完毕,虚拟DOM才更新
第五个阶段 组件更新完成
componentDidUpdate方法:
- 第一个参数是旧的属性数据
- 第二个参数是旧的状态数据
组件实例化对象上的是新的
属性数据
组件实例化对象上的是新的
状态数据
此时虚拟DOM也已经更新完成了
组件更新完成了,我们可以在这个阶段发送请求,处理事件等等,该方法执行完毕,并没有说明存在期的结束,存在期仍然继续,只是一次更新的结束,所有组件生命周期方法this都指向组件实例化对象
// 定义组件 class GoTop extends Component { // 构造函数 constructor(props) { super(props); this.state = { text: props.text } } // 存在期五个阶段 // 1 组件即将接收新的属性数据 componentWillReceiveProps(newProps) { console.log(111, 'componentWillRecieveProps', newProps, this.props) // 将属性数据,存储到状态中 this.setState({ text: newProps.text }) } // 2 组件是否更新 shouldComponentUpdate(newProps, newState) { console.log(222, 'shouldComponentUpdate', newProps, this.props, 'state', newState, this.state) // 是否可以更新 // return true; // 根据属性或者状态的改变来优化 return newProps.text !== this.props.text || newState.text !== this.state.text } // 3 组件即将更新 componentWillUpdate(newProps, newState) { console.log(333, 'componentWillUpdate', newProps, this.props, 'state', newState, this.state, findDOMNode(this).innerHTML) } // 4 渲染虚拟DOM render() { console.log(444, 'render', this.props, 'state', this.state) // return <span>{this.props.text}</span> return <span>{this.state.text}</span> } // 5 组件更新完成 componentDidUpdate(oldProps, oldState) { console.log(555, 'componentDidUpdate', oldProps, this.props, 'state', oldState, this.state, findDOMNode(this).innerHTML) } // 组件创建完成 componentDidMount() { window.onscroll = () => { // 移动超过300显示返回顶部 if (window.scrollY > 300) { this.setState({ text: '返回顶部' }) } else { // 显示头条新闻 this.setState({ text: '头条新闻' }) } // console.log(window.scrollY) } } }
到此这篇关于React中父子组件通信详解的文章就介绍到这了,更多相关React组件通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!