1. 父子组件通信
说明:
- 父组件通过props属性,将一般数据传递给子组件
- react是单行数据流, 因此,如果子组件需要将数据传递给父组件
- 首先父组件通过props属性父组件的方法下发给子组件
- 子组件通过调用父组件将方法传参的方式将数据传递给父组件
示例代码:
父组件代码:
import React from 'react';
import './App.css';
import List from './List'
class App extends React.Component {
// 父组件定义状态
state = {
list: [
{
id: 0,
doing: "吃饭"
},
{
id: 1,
doing: "睡觉"
},
{
id: 2,
doing: "打豆豆"
}
],
nextId: 3,
inputValue:""
}
// 添加内容
addDoing = () =>{
// 获取输入框中的内容
let value = this.input.value.trim()
// 判断内容是否为空
if(!value){
console.log("输入内容不能为空");
return
}
// 不为空就将内容添加到状态中
let {list,nextId} = this.state
list.unshift({
id:nextId,
doing:value
})
this.setState(() => ({
nextId: ++nextId,
list
}))
// 清空输入空内容
this.input.value = ""
}
// 删除状态的方法
deleteList = (index) => {
// 删除完成的内容
let { list } = this.state
list.splice(index,1)
this.setState(() => ({
list
}))
}
render(){
// 取出数据
let {list} = this.state
return (
<div className="App">
<h2>添加内容</h2>
<div>
<input type="text" ref={input => this.input = input}/>
<button onClick={ this.addDoing }>添加</button>
</div>
{/*
// 父组件向子组件同信
1. 父向子通信:将父组件的数据通过props 传递给子组件
2. 子向父通信: 将父组件的方法下发给子组件,子组件将调用向父组件传参
*/}
<List
list={list}
deleteList = {this.deleteList}
/>
</div>
)
}
}
export default App;
子组件代码:
import React from 'react'
class List extends React.Component{
// 子组件向父组件同信
complete = (index) => {
// 1. 获取父组件传递过来的方法
let {deleteList} = this.props
// 2. 调用方法,将数据传递给父组件
deleteList(index)
}
render(){
// 通过props获取父组件传递过来的数据
console.log(this.props)
let {list} = this.props
return (
<div>
<ul>
{
list.map((item,index) => (
<li key={item.id}>
{index}:{ item.doing}
<button onClick={() => (this.complete(index))}>
完成
</button>
</li>
))
}
</ul>
</div>
)
}
}
export default List
这种传递方式有弊端,就是不是父子组件传递数据,不是很方便
2. 使用消息订阅(subscribe)-发布(publish)机制
2.1 发布订阅机制的了解
- 订阅就像是绑定事件监听, 发布就像触发事件
- 发布订阅机制需要使用到第三方的工具库
pubsub-js
- 通过subscribe方法订阅或者叫绑定自定义事件
- 通过publish 方法触发自定义事件的执行, 也叫发布
- 优点: 对组件的关系没有限制
2.2 使用
下载安装
$ npm install pubsub-js --save
使用的语法:
// 发布消息(就相当于触发事件)
// 这里就相当于触发了search事件,并且传递实参hello world
PubSub.publish('seach', 'hello world')
// 订阅消息(就相当于绑定事件)
PubSub.subscribe('seach', function(msg,data){
// msg 是消息名 就是search
// data 就是发布消息时传递过来的数据
})
示例代码如下:
修改上面的示例:
父组件:
在父组件的componentDidMount
生命周期函数中订阅消息
class App extends React.Component {
// 父组件定义状态
state = {
list: [
{
id: 0,
doing: "吃饭"
},
{
id: 1,
doing: "睡觉"
},
{
id: 2,
doing: "打豆豆"
}
],
nextId: 3,
inputValue:""
}
// 组件挂在完毕后订阅事件
componentDidMount(){
PubSub.subscribe("delete", (msg ,index) => {
/*
自定义事件接受两个参数
1. 第一个参数为自定义事件名,也叫消息名
2. 第二个参数是发布消息,也就是触发自定义事件时传递的参数
*/
// 删除完成的内容
let { list } = this.state
list.splice(index,1)
this.setState(() => ({
list
}))
})
}
render(){
// 取出数据
let {list} = this.state
return (
<div className="App">
<h2>添加内容</h2>
<div>
<input type="text" ref={input => this.input = input}/>
<button onClick={ this.addDoing }>添加</button>
</div>
{/*
1. 父向子通信:将父组件的数据通过props 传递给子组件
2. 使用发布订阅机制就不用在向子组件传递函数了
*/}
<List
list={list}
/>
</div>
)
}
}
子组件
通过publish发布消息, 也可以理解为触发自定义事件
class List extends React.Component{
// 在点击事件函数中发布消息, 并传递参数
complete = (index) => {
// 发布事件,触发自定义事件的执行
PubSub.publish("delete", index)
}
render(){
// 通过props获取父组件传递过来的数据
console.log(this.props)
let {list} = this.props
return (
<div>
<ul>
{
list.map((item,index) => (
<li key={item.id}>
{index}:{ item.doing}
<button onClick={() => (this.complete(index))}>
完成
</button>
</li>
))
}
</ul>
</div>
)
}
}
3. redux 状态管理
通过redux可以实现任意组件间的通信,
集中式管理多个组件共享的状态,
而pubsub-js
并不是状态管理,状态还是要定义在组件中,只不过是使用发布订阅机制通信
redux后面详谈