实战 React 之组件通信(父组件向子组件,子组件向父组件)
前言
React 与 Vue 最大的相通之处就是两者都是单页面应用,页面与页面之间,功能与功能之间,都是一个个的组件构成。组件也有层级结构,父与子关系,子与父关系,兄弟关系等。那么有关系的组件之间如何通信?将是本文探讨的主题。
一、父组件与子组件通信
父组件向子组件传值直接通过属性的方式,子组件通过 props 接收。
父组件调用子组件方法是通过给子组件绑定 ref 获取子组件实例。随后找到子组件的方法并调用。
父组件 TodoList.js
import React from 'react';
import TodoItem from './TodoItem';
export default class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {
taskList: []
};
this.taskList = [];
}
//添加任务列表
add() {
var value = this.refs.input.value;
this.taskList.push({text: value});
this.setState({
taskList: this.taskList
})
}
del() {
//通过ref找到子组件实例,调用del方法。
this.refs.item.del('完成');
}
render() {
return <div>
<input type="text" ref="input"/>
<button onClick={() => this.add()}>添加待办</button>
<TodoItem
taskList={this.state.taskList}
ref="item"
/>
<button onClick={() => this.del()}>删除包含完成的事项</button>
</div>
}
}
子组件 TodoItem.js
import React from 'react';
export default class TodoItem extends React.Component {
constructor(props) {
super(props);
this.state = {
taskList:[]
}
}
componentWillReceiveProps(state){
//获取父组件最新的taskList,更新子组件的taskList
this.setState({
taskList:state.taskList
})
}
//提供del方法给父组件使用
del(str){
var taskList = this.state.taskList.filter((item)=>item.text.indexOf(str)<0);
this.setState({
taskList:taskList
})
}
render() {
return <div>
{this.state.taskList.map((item,index)=>{
return<div key={index}>
{item.text}
</div>
})}
</div>
}
}
二、子组件与父组件通信
子组件调用父组件的方法也是通过 props 属性。
父组件 TodoList.vue
import React from 'react';
import TodoItem from './TodoItem';
export default class TodoList extends React.Component {
constructor(props) {
super(props);
this.state = {
taskList: [{text:"完成国际会议",done:true},{text:"未完成国内会议",done:false}],
tip:'未删除'
};
}
//父组件的方法供子组件调用
del(str) {
var taskList = this.state.taskList.filter((item)=>!item.done);
this.setState({
taskList:taskList,
tip:str
})
}
render() {
return <div>
<TodoItem
taskList={this.state.taskList}
ref="item"
onFilter={(str)=>this.del(str)}
/>
<div>结果:{this.state.tip}</div>
</div>
}
}
子组件 TodoItem.vue
import React from 'react';
export default class TodoItem extends React.Component {
constructor(props) {
super(props);
this.state = {
taskList:props.taskList
}
}
componentWillReceiveProps(state){
console.log(state);
//获取父组件最新的taskList,更新子组件的taskList
this.setState({
taskList:state.taskList
})
}
//提供del方法给父组件使用
del(){
const {onFilter} = this.props;
if(onFilter){
onFilter('删除完成')
}
}
render() {
return <div>
{this.state.taskList.map((item,index)=>{
return<div key={index}>
{item.text}
</div>
})}
<button onClick={() => this.del()}>删除包含完成的事项</button>
</div>
}
}
三、其他组件通信
其他组件通信可使用 Redux 状态管理工具。其核心思想是将所有状态集中管理,一处有变动。其他地方同步更新。可参考 Redux 官方文档。