第十節(jié): React組件間的通信

  1. 父子組件通信
    說明:

父組件通過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ù),不是很方便

  1. 使用消息訂閱(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>
    )
}

}

  1. redux 狀態(tài)管理
    通過redux可以實(shí)現(xiàn)任意組件間的通信,

集中式管理多個組件共享的狀態(tài),

而pubsub-js并不是狀態(tài)管理,狀態(tài)還是要定義在組件中,只不過是使用發(fā)布訂閱機(jī)制通信

redux后面詳談

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容