- 父子組件通信
說明:
父組件通過props屬性,將一般數(shù)據(jù)傳遞給子組件
react是單行數(shù)據(jù)流, 因此,如果子組件需要將數(shù)據(jù)傳遞給父組件
首先父組件通過props屬性父組件的方法下發(fā)給子組件
子組件通過調(diào)用父組件將方法傳參的方式將數(shù)據(jù)傳遞給父組件
示例代碼:
父組件代碼:
import React from 'react';
import './App.css';
import List from './List'
class App extends React.Component {
// 父組件定義狀態(tài)
state = {
list: [
{
id: 0,
doing: "吃飯"
},
{
id: 1,
doing: "睡覺"
},
{
id: 2,
doing: "打豆豆"
}
],
nextId: 3,
inputValue:""
}
// 添加內(nèi)容
addDoing = () =>{
// 獲取輸入框中的內(nèi)容
let value = this.input.value.trim()
// 判斷內(nèi)容是否為空
if(!value){
console.log("輸入內(nèi)容不能為空");
return
}
// 不為空就將內(nèi)容添加到狀態(tài)中
let {list,nextId} = this.state
list.unshift({
id:nextId,
doing:value
})
this.setState(() => ({
nextId: ++nextId,
list
}))
// 清空輸入空內(nèi)容
this.input.value = ""
}
// 刪除狀態(tài)的方法
deleteList = (index) => {
// 刪除完成的內(nèi)容
let { list } = this.state
list.splice(index,1)
this.setState(() => ({
list
}))
}
render(){
// 取出數(shù)據(jù)
let {list} = this.state
return (
<div className="App">
<h2>添加內(nèi)容</h2>
<div>
<input type="text" ref={input => this.input = input}/>
<button onClick={ this.addDoing }>添加</button>
</div>
{/*
// 父組件向子組件同信
1. 父向子通信:將父組件的數(shù)據(jù)通過props 傳遞給子組件
2. 子向父通信: 將父組件的方法下發(fā)給子組件,子組件將調(diào)用向父組件傳參
*/}
<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. 調(diào)用方法,將數(shù)據(jù)傳遞給父組件
deleteList(index)
}
render(){
// 通過props獲取父組件傳遞過來的數(shù)據(jù)
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
這種傳遞方式有弊端,就是不是父子組件傳遞數(shù)據(jù),不是很方便
- 使用消息訂閱(subscribe)-發(fā)布(publish)機(jī)制
2.1 發(fā)布訂閱機(jī)制的了解
訂閱就像是綁定事件監(jiān)聽, 發(fā)布就像觸發(fā)事件
發(fā)布訂閱機(jī)制需要使用到第三方的工具庫 pubsub-js
通過subscribe方法訂閱或者叫綁定自定義事件
通過publish 方法觸發(fā)自定義事件的執(zhí)行, 也叫發(fā)布
優(yōu)點(diǎn): 對組件的關(guān)系沒有限制
2.2 使用
下載安裝
$ npm install pubsub-js --save
使用的語法:
// 發(fā)布消息(就相當(dāng)于觸發(fā)事件)
// 這里就相當(dāng)于觸發(fā)了search事件,并且傳遞實(shí)參hello world
PubSub.publish('seach', 'hello world')
// 訂閱消息(就相當(dāng)于綁定事件)
PubSub.subscribe('seach', function(msg,data){
// msg 是消息名 就是search
// data 就是發(fā)布消息時傳遞過來的數(shù)據(jù)
})
示例代碼如下:
修改上面的示例:
父組件:
在父組件的componentDidMount生命周期函數(shù)中訂閱消息
class App extends React.Component {
// 父組件定義狀態(tài)
state = {
list: [
{
id: 0,
doing: "吃飯"
},
{
id: 1,
doing: "睡覺"
},
{
id: 2,
doing: "打豆豆"
}
],
nextId: 3,
inputValue:""
}
// 組件掛在完畢后訂閱事件
componentDidMount(){
PubSub.subscribe("delete", (msg ,index) => {
/*
自定義事件接受兩個參數(shù)
1. 第一個參數(shù)為自定義事件名,也叫消息名
2. 第二個參數(shù)是發(fā)布消息,也就是觸發(fā)自定義事件時傳遞的參數(shù)
*/
// 刪除完成的內(nèi)容
let { list } = this.state
list.splice(index,1)
this.setState(() => ({
list
}))
})
}
render(){
// 取出數(shù)據(jù)
let {list} = this.state
return (
<div className="App">
<h2>添加內(nèi)容</h2>
<div>
<input type="text" ref={input => this.input = input}/>
<button onClick={ this.addDoing }>添加</button>
</div>
{/*
1. 父向子通信:將父組件的數(shù)據(jù)通過props 傳遞給子組件
2. 使用發(fā)布訂閱機(jī)制就不用在向子組件傳遞函數(shù)了
*/}
<List
list={list}
/>
</div>
)
}
}
子組件
通過publish發(fā)布消息, 也可以理解為觸發(fā)自定義事件
class List extends React.Component{
// 在點(diǎn)擊事件函數(shù)中發(fā)布消息, 并傳遞參數(shù)
complete = (index) => {
// 發(fā)布事件,觸發(fā)自定義事件的執(zhí)行
PubSub.publish("delete", index)
}
render(){
// 通過props獲取父組件傳遞過來的數(shù)據(jù)
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>
)
}
}
- redux 狀態(tài)管理
通過redux可以實(shí)現(xiàn)任意組件間的通信,
集中式管理多個組件共享的狀態(tài),
而pubsub-js并不是狀態(tài)管理,狀態(tài)還是要定義在組件中,只不過是使用發(fā)布訂閱機(jī)制通信
redux后面詳談