空数组
的情况,第一个参数里的函数就相当于是class组件中的组件挂载完毕钩子(componentDidMount)。不传 或者 是非空数组
,此时第一个参数相当于组件更新完毕的钩子(componentDidUpdate)。
npm install pubsub-js
import PubSub from 'pubsub-js'
//PubSub.publish('MY TOPIC', 'hello world!');
PubSub.publish('GamesNews','通知:在我校(ChildA)举办运动会的时间定于10月16日');
useEffect
钩子),核心代码如下:import PubSub from 'pubsub-js'
//订阅运动会消息
const subscriberGamesNew = function(msg, data){
console.log('ChildB 订阅的消息--subscriberGamesNew---');
console.log( msg, data );//msg-订阅的topic data-消息内容
}
useEffect(()=>{
//subscribe-订阅的方法 'GamesNews'-订阅的主题
let token = PubSub.subscribe('GamesNews', subscriberGamesNew);
console.log('token',token);
},[])//这里第二个参数是空数组 [],这种情况相当于class组件中 "组件挂载完毕的钩子"
语法:
const token1 = PubSub.subscribe('GamesNews', mySubscribers);//订阅 GamesNews
//取消订阅
PubSub.unsubscribe(token1);
或
PubSub.unsubscribe('GamesNews');
上面函数可以优化一下,根据主题取消,如下:
const myUnsubscribe =(topic)=>{
PubSub.unsubscribe(topic); //取消订阅的GamesNews
console.log('取消订阅运动会消息---成功!!!');
}
<button onClick={()=>myUnsubscribe('GamesNews')}>取消订阅运动会消息</button>
import root from '../index';
//卸载组件---卸载所有
const unMountAll =()=>{
//卸载组件 root
root.unmount();
}
<button onClick={unMountAll}>卸载所有组件</button>
卸载/渲染
B组件的按钮)import React from "react";
import ChildA from "./ChildA";
import ChildB from "./ChildB";
import './index.css'
import root from '../index';
function Parent() {
const [mountChildBFlag,setMountChildFlag] = React.useState(true);
//卸载组件---卸载所有
const unMountAll =()=>{
//卸载组件 root
root.unmount();
}
return(
<div className="parent">
我是父组件!
<div className="childA">
<ChildA notice={'通知——今天放假!'}/>
</div>
{/*
*/}
{/* 这里根据 mountChildBFlag 控制B组件的状态 */}
{
mountChildBFlag ?
<div className="childB">
<ChildB notice={'通知——今天放假!'} />
</div>
: ""
}
<br /><br />
<button onClick={()=>setMountChildFlag(!mountChildBFlag)}>卸载B组件/渲染B组件</button>
<br /><br />
<button onClick={unMountAll}>卸载所有组件</button>
</div>
)
}
export default Parent;
import React from "react";
import PubSub from 'pubsub-js'
function ChildA(props){
const stuNameRef = React.useRef();
//发布运动会消息 按钮触发
function publishGamesNews(){
// 发布运动会消息 topic-->GamesNews
PubSub.publish('GamesNews','通知:在我校(ChildA)举办运动会的时间定于10月16日');
console.log('-----ChildA 发布了 GamesNews 消息----');
}
// 发布学生消息 开除的学生
function expelStuSubmit(event){
event.preventDefault();//非受控组件 只取表单数据,但阻止表单提交,实现页面无刷新
const stuName = stuNameRef.current.value;
PubSub.publish('stusInfo',{stuName:stuName,schoolName:'ChildA-School',stuState:'被开除'});
}
return(
<div>
我是子组件A!!!
<br /><br />
收到来自于父组件的数据:{props.notice}
<br /><br />
<button onClick={publishGamesNews}>发布运动会消息</button>
<br /><br />
<form onSubmit={expelStuSubmit}>
学生姓名:<input type="text" ref={stuNameRef} name="stuName"/>
<button>开除学生</button>
</form>
</div>
)
}
export default ChildA;
import PubSub from 'pubsub-js'
import { useEffect,useState } from 'react';
function ChildB(props){
const [gamesNews,setGamesNews] = useState('等通知……');
const [stusInfo,setStuInfo] = useState(
[
{stuName:'学生1',schoolName:'ChildA-School',stuState:'在校'},
{stuName:'学生2',schoolName:'ABC学校',stuState:'离校'},
{stuName:'张三',schoolName:'ChildA-School',stuState:'在校'},
{stuName:'李四',schoolName:'XXX附属中学',stuState:'托管'},
{stuName:'王五',schoolName:'ChildA-School',stuState:'在校'},
]
);
//我的订阅方法
const mySubscribers = function(msg, data){
console.log('ChildB 订阅的消息--mySubscribers---');
// console.log( msg, data );//msg-订阅的topic data-消息内容
//将订阅到的新消息进行更新
if('GamesNews'===msg){
console.log('订阅到运动会的消息是:',data);
setGamesNews(data);
}else if('stusInfo'===msg){
console.log('订阅到开除的学生是:',data);
// const newStuInfo = [...stusInfo,data];//这个不去重,追加数据
//这个地方需要注意stusInfo 和 data的类型
const newStuInfo = stusInfo.map((stu)=>{
return data.stuName===stu.stuName ? data : stu;
});
setStuInfo(newStuInfo);
}
}
useEffect(()=>{
//subscribe-订阅的方法
const token1 = PubSub.subscribe('GamesNews', mySubscribers);//订阅 GamesNews
const token2 = PubSub.subscribe('stusInfo', mySubscribers);// 订阅 stusInfo
console.log('token1---',token1);
console.log('token2---',token2);
return ()=>{
//这个返回函数,相当于class中的“组件将要卸载的钩子” 在这里可以取消订阅
console.log('ChildB组件...被卸载了');
PubSub.unsubscribe(token1); //取消订阅
}
},[])//这里第二个参数是空数组 [],这种情况相当于class组件中 "组件挂载完毕的钩子"
//取消订阅
const myUnsubscribe =(topic)=>{
PubSub.unsubscribe(topic); //取消订阅的GamesNews
console.log('取消订阅运动会消息---成功!!!');
}
return(
<div>
我是子组件B!!!
<br /><br />
收到来自于父组件的数据:{props.notice}
<br /><br /><br />
订阅1——运动会消息:{gamesNews}
<br />
<button onClick={()=>myUnsubscribe('GamesNews')}>取消订阅运动会消息</button>
<br /><br /><br />
订阅2——学生消息:
<table>
<thead>
<tr>
<th>学生姓名</th>
<th>所在学校</th>
<th>状态</th>
</tr>
</thead>
<tbody>
{stusInfo.map((stu,index)=>{
return <tr key={index}>
<td>{stu.stuName}</td>
<td>{stu.schoolName}</td>
<td>{stu.stuState}</td>
</tr>
})}
</tbody>
</table>
</div>
)
}
export default ChildB;
.parent{
background-color: blueviolet;
border: 1px solid;
height: 900px;
width: 600px;
text-align: center;
}
.childA{
background-color: green;
height: 170px;
margin: 20px;
}
.childB{
background-color: grey;
height: 400px;
margin: 20px;
}