1. 程式人生 > >非巢狀元件間通訊 轉載

非巢狀元件間通訊 轉載

非巢狀元件間通訊

非巢狀元件,就是沒有任何包含關係的元件,包括兄弟元件以及不在同一個父級中的非兄弟元件。對於非巢狀元件,可以採用下面兩種方式:

  • 利用二者共同父元件的 context 物件進行通訊
  • 使用自定義事件的方式

如果採用元件間共同的父級來進行中轉,會增加子元件和父元件之間的耦合度,如果元件層次較深的話,找到二者公共的父元件不是一件容易的事,當然還是那句話,也不是不可以...
這裡我們採用自定義事件的方式來實現非巢狀元件間的通訊。
我們需要使用一個 events 包:

npm install events --save

新建一個 ev.js,引入 events 包,並向外提供一個事件物件,供通訊時使用:

import { EventEmitter } from "events";
export default new EventEmitter(); 

App.js:

import React, { Component } from 'react';

import Foo from "./Foo"; import Boo from "./Boo"; import "./App.css"; export default class App extends Component{ render(){ return( <div> <Foo /> <Boo /> </div> ); } } 

Foo.js:

import React,{ Component } from "react";
import emitter from "./ev" export default class Foo extends Component{ constructor(props) { super(props); this.state = { msg:null, }; } componentDidMount(){ // 宣告一個自定義事件 // 在元件裝載完成以後 this.eventEmitter = emitter.addListener("callMe",(msg)=>{ this.setState({ msg }) }); } // 元件銷燬前移除事件監聽 componentWillUnmount(){ emitter.removeListener(this.eventEmitter); } render(){ return( <div> { this.state.msg } 我是非巢狀 1 號 </div> ); } } 

Boo.js:

import React,{ Component } from "react";
import emitter from "./ev" export default class Boo extends Component{ render(){ const cb = (msg) => { return () => { // 觸發自定義事件 emitter.emit("callMe","Hello") } } return( <div> 我是非巢狀 2 號 <button onClick = { cb("blue") }>點選我</button> </div> ); } } 

自定義事件是典型的釋出/訂閱模式,通過向事件物件上新增監聽器和觸發事件來實現元件間通訊。