您当前的位置: 首页 > 

暂无认证

  • 7粉丝

    0关注

    0博文

    0收益

  • 7浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【React组件】github搜索案例之 兄弟组件通信---PubSubJS / fetch

发布时间:2022-07-06 09:49:03 ,浏览量:44

文章目录
  • 🏧消息订阅-发布机制---axios发送请求
    • 🔨工具库
    • 📢订阅消息
    • 🔊发布消息
    • 📝实现步骤
    • 📌扩展---fetch发送请求
    • 📦总结

💥回顾上篇文章的github案例,通过父子组件传值进而实现了兄弟组件之间的通信。 本篇文章教你 如何直接在兄弟组件之间进行通信

在这里插入图片描述

🏧消息订阅-发布机制—axios发送请求

该方法可以实现任意组件的通信 假设A组件想给B组件发送消息(数据),A组件发布消息,B组件(接收数据)就要订阅该消息,这样B组件就能收到A组件传过来的数据了。

在上篇文章的github案例中,search组件发送请求返回的数据用来发布消息List组件用来订阅该消息,这样通过消息订阅-发布机制就实现了兄弟组件通信。

🔨工具库

PubSubJS

下载PubSubJS:

npm install pubsub-js --save

引入PubSubJS:

import PubSub from 'pubsub-js'   
📢订阅消息
PubSub.subscribe('msg', function(msg,data){ }); 

第一个参数msg是订阅的事件名称。 第二个参数function(msg,data){ }是别人发布了消息之后执行的函数 (data是别人发布消息传递过来的数据)

🔊发布消息
PubSub.publish('msg', data)
📝实现步骤

1️⃣分别在Search组件和List组件中引入PubSubJS

import PubSub from 'pubsub-js' 

2️⃣List组件订阅消息:当组件挂载完毕时订阅消息

componentDidMount() {
  this.token = PubSub.subscribe('atguigu', (_, stateObj) => {
    this.setState(stateObj)
  })
}

3️⃣Search组件使用axios发送请求获取数据并发布消息:

在这里插入图片描述

4️⃣List组件将要卸载时,取消订阅:

componentWillUnmount() {
  PubSub.unsubscribe(this.token)
}
📌扩展—fetch发送请求

利用fetch()方法发送请求,原先使用axios发送请求,利用XMLHttpRequest封装的一个库,将一个复杂的过程,拆分成多个小操作,例如xhr.open()/xhr.send()

而fetch是基于 Promise的一个内置的原生函数,不需要下载,不再使用XmlHttpRequest对象提交ajax请求,使用的是关注分离的设计思想,老版本浏览器可能不支持。

Search组件

search = async () => {
  // 获取用户的输入(解构赋值的连续写法+重命名)
  const { keyWordElement: { value: keyWord } } = this
  // 发送请求前通知List更新状态
  PubSub.publish('atguigu', { isFirst: false, isLoading: true })
  // 发送网络请求----使用fetch发送
  try {
    //是否能够联系服务器成功
    const response = await fetch(`/api1/search/users?q=${keyWord}`)
    //拿到数据
    const data = await response.json()
    PubSub.publish('atguigu', { isLoading: false, users: data.items })
  } catch (error) {
    PubSub.publish('atguigu', { isLoading: false, err: error.message })
  }
}

使用PubSub + fetch实现整体代码:

index.js:

// 引入react核心库
import React from 'react'
// 引入ReactDOM
import ReactDOM from 'react-dom/client'
// 引入App
import App from './App'

// 创建虚拟DOM
const root = ReactDOM.createRoot(document.getElementById('root'))
// 渲染虚拟DOM到页面
root.render(
  
  {/* 检查App组件以及子组件里的一些代码是否有不合理的地方 */}
  
  
)

父组件App.jsx:

import React, { Component } from 'react';
import Search from './components/Search'
import List from './components/List';

export default class App extends Component {
  render() {
    return (
      
        
        
      
    );
  }
}

子组件Search_index.jsx:

import React, { Component } from 'react'
import PubSub from 'pubsub-js'
// import axios from 'axios'

export default class Search extends Component {
  search = async () => {
    // 获取用户的输入(解构赋值的连续写法+重命名)
    const { keyWordElement: { value: keyWord } } = this
    // 发送请求前通知List更新状态
    PubSub.publish('atguigu', { isFirst: false, isLoading: true })
    // 发送网络请求----使用fetch发送(未优化)
    // fetch(`/api1/search/users2?q=${keyWord}`).then(
    //   response => {
    //     console.log('成功了')
    //     return response.json()
    //   },
    //   error => {
    //     console.log('失败了', error)
    //     return new Promise(() => { })
    //   }
    // ).then(
    //   response => { console.log('获取数据成功了', response) },
    //   error => { console.log('获取数据失败了', error) }
    // )
    
    // 发送网络请求----使用fetch发送(优化)
    // fetch(`/api1/search/users2?q=${keyWord}`).then(
    //   response => {
    //     console.log('成功了')
    //     return response.json()
    //   }
    // ).then(
    //   response => { console.log('获取数据成功了', response) }
    // ).catch(
    //   (error) => {
    //     console.log(error)
    //   }
    // )

    // 发送网络请求----使用fetch发送(最优化)
    try {
      const response = await fetch(`/api1/search/users?q=${keyWord}`)
      const data = await response.json()
      PubSub.publish('atguigu', { isLoading: false, users: data.items })
    } catch (error) {
      PubSub.publish('atguigu', { isLoading: false, err: error.message })
    }
  }

  render() {
    return (
      
        搜索github用户
        
           this.keyWordElement = c} type="text" placeholder="输入关键词点击搜索" /> 
          搜索
        
      
    )
  }
}

子组件List_index.jsx:

import React, { Component } from 'react'
import PubSub from "pubsub-js";
import './index.css'

export default class List extends Component {

  state = { //初始化状态
    users: [], //users初始值为数组
    isFirst: true, //是否为第一次打开页面
    isLoading: false, //标识是否处于加载中
    err: '' //存储请求相关的错误信息
  }

  // 组件挂载完毕之后订阅消息
  componentDidMount() {
    this.token = PubSub.subscribe('atguigu', (_, stateObj) => {
      this.setState(stateObj)
    })
  }

  // 组件将要卸载时,取消订阅
  componentWillUnmount() {
    PubSub.unsubscribe(this.token)
  }


  render() {
    const { users, isFirst, isLoading, err } = this.state
    return (
      
        {
          isFirst ? 欢迎使用,输入关键字,随后点击搜索 :
            isLoading ? Loading..... :
              err ? {err} :
                users.map((userObj) => {
                  return (
                    
                      
                        
                      
                      {userObj.login}
                    
                  )
                })
        }
      
    )
  }
}

setupProxy.js:

const { createProxyMiddleware } = require('http-proxy-middleware')

module.exports = function (app) {
  app.use(
    createProxyMiddleware('/api1', {
      target: 'http://localhost:5000',
      changeOrigin: true,
      pathRewrite: { '^/api1': '' }
    })
  )
}
📦总结

1️⃣设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办。

2️⃣ES6小知识点:解构赋值+重名名

let obj = {a:{b:1}}
    const {a} =obj;  //传统解构赋值
    const {a:{b}} = obj;  //连续解构赋值
    const {a:{b:value}} = obj;  //连续解构赋值+重命名

3️⃣消息订阅与发布机制

  1. 先订阅,再发布(理解:有一种隔空对话的感觉)
  2. 适用于任意组件间通信
  3. 要在组件的componentWillUnmount中取消订阅

4️⃣fetch发送请求(关注分离的设计思想)

try {
      const response = await fetch(`/api1/search/user2?q=${keyWord}`)
      const data = await response.json()
      console.log(data)
    } catch(error) {
      console.log('请求出错',error)
    }

今天的分享就到这里啦 ✨ 如果对你有帮助的话,还请👉🏻关注💖点赞🤞收藏⭐评论🔥哦 不定时回访哟🌹

关注
打赏
1652792496
查看更多评论
广告位
立即登录/注册

微信扫码登录

0.3485s