在nextjs項(xiàng)目中,發(fā)現(xiàn)兩個(gè)組件沒(méi)啥關(guān)系,例如一個(gè)是一直存在的頭部組件,另一個(gè)是頁(yè)面中的組件,當(dāng)我點(diǎn)擊頭部組件中的特定按鈕時(shí),把數(shù)據(jù)傳遞到頁(yè)面組件中,頁(yè)面組件接受到canshu數(shù)據(jù)后在做其他操作,那么他們兩個(gè)如何通訊,通過(guò)context配合觀察者模式實(shí)現(xiàn)。
- 首先在其共同的祖先組件中使用context
下面的代碼文件是根路由組件Layout.js
其中children就是根據(jù)路由渲染的對(duì)應(yīng)的頁(yè)面
....
import {ConContext} from "../utils/test1";
import EventBus from "../utils/test";
const Layout = () => {
<ConContext.Provider value={EventBus()}>
<Header />
{children}
<Footer></Footer>
</ConContext.Provider>
}
export default Layout
test1.js
創(chuàng)建context
import { createContext } from 'react';
export const ConContext = createContext(null);
test.js
使用 useEffect 包裝下,否則會(huì)在服務(wù)端渲染,而服務(wù)端又沒(méi)有瀏覽器對(duì)象,所以會(huì)報(bào)錯(cuò),導(dǎo)致打包失敗,下面代碼中,注釋的代碼就會(huì)報(bào)找不到document,所以使用useEffect包裝下創(chuàng)建了一個(gè)自定義hook勾子 useEvent,這個(gè)鉤子創(chuàng)建一個(gè)變量用于接收EventBus這個(gè)類,為什么要在useEffect 創(chuàng)建EventBus呢,因?yàn)橹挥性趗seEffect中才能拿到瀏覽器對(duì)象,然后在返回變量。然后導(dǎo)出這個(gè)useEvent文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-606635.html
"use client"
import {useEffect, useState} from 'react'
// 使用 useEffect 包裝下,否則會(huì)在服務(wù)端渲染,而服務(wù)端又沒(méi)有瀏覽器對(duì)象,所以會(huì)報(bào)錯(cuò),導(dǎo)致打包失敗
const useEvent = () => {
const [val, setVal] = useState('')
useEffect(() => {
class EventBus {
constructor() {
this.bus = document.createElement('fakeelement');
}
addEventListener(event, callback) {
this.bus.addEventListener(event, callback);
}
removeEventListener(event, callback) {
this.bus.removeEventListener(event, callback);
}
dispatchEvent(event, detail = {}){
this.bus.dispatchEvent(new CustomEvent(event, { detail }));
}
}
setVal(new EventBus)
},[])
return val
}
export default useEvent
// "use client"
// class EventBus {
// constructor() {
// this.bus = document.createElement('fakeelement');
// }
// addEventListener(event, callback) {
// this.bus.addEventListener(event, callback);
// }
// removeEventListener(event, callback) {
// this.bus.removeEventListener(event, callback);
// }
// dispatchEvent(event, detail = {}){
// this.bus.dispatchEvent(new CustomEvent(event, { detail }));
// }
// }
// export default new EventBus
- 在header中觸發(fā)事件,
header.js
使用useContext接收數(shù)據(jù)
import React, {useState, useContext} from 'react';
const Header = () => {
const EventBus = useContext(ConContext)
// 點(diǎn)擊按鈕時(shí)觸發(fā)
const clickTab = (url) => {
setOpenMenu(false)
// 點(diǎn)擊頭部菜單切換輪播圖開(kāi)始
// EventBus.dispatchEvent('myEvent', {log: 2})
// 點(diǎn)擊頭部菜單切換輪播圖結(jié)束
push(url)
}
}
export default Header
- 在對(duì)應(yīng)的頁(yè)面組件中接收myEvent這個(gè)自定義事件
import React, { useEffect,useRef, useContext } from "react";
import { ConContext } from '../../utils/test1';
const Products = (props) => {
const EventBus = useContext(ConContext)
console.log(EventBus,'EventBus');
const slider = useRef();
const handleEvent = (e) => {
slider.current.goTo(e.detail.log)
}
useEffect(() => {
EventBus.addEventListener('myEvent', handleEvent)
}, [EventBus]);
}
export default Products;
參考:10種React組件之間通信的方法文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-606635.html
到了這里,關(guān)于react當(dāng)我們有兩個(gè)完全不相關(guān)的組件想要通信時(shí),就可以利用這種模式,其中一個(gè)組件負(fù)責(zé)訂閱某個(gè)消息,而另一個(gè)元素則負(fù)責(zé)發(fā)送這個(gè)消息。使用Context配合的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!