第二十九章 使用消息订阅发布实现组件通信

PubSubJS库介绍

如果你想在React中使用第三方库来实现Pub/Sub机制,PubSubJS是一个不错的选择。它是一个轻量级的库,可以在浏览器和Node.js环境中使用。

PubSubJS提供了一个简单的API,可以让你在应用程序中订阅和发布消息。你可以使用npm来安装它:

npm install pubsub-js

1-引入使用

import PubSub from 'pubsub-js'

2-首先订阅消息

PubSub.subscribe('List',function(msg, data){
    
     console.log(msg, data)})

用于接收发布的信息。

3-发布消息

PubSub.publish('List',data)

4-取消订阅消息

PubSub.unsubscribe(this.token)

案例使用

现在有一个页面,有两个兄弟组件

  • Search组件获取输入的关键字,然后交给List组件去网络请求。
  • List组件展示github的用户列表

1-App组件代码

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

export default class App extends Component {
    
    
  render() {
    
    
    return (
      <div className="container">
        <Search/>
        <List/>
    </div>
    )
  }
}

2-Search组件代码

import React, {
    
     Component } from 'react'
import PubSubJs from 'pubsub-js'

export default class Search extends Component {
    
    

  searchHandle = () => {
    
    
    const {
    
    KeyVal:{
    
    value}} = this
    PubSubJs.publish('getSearchVal',value)
  }

  render() {
    
    
    return (
      <section className="jumbotron">
      <h3 className="jumbotron-heading">Search Github Users</h3>
      <div>
        <input ref={
    
    c=>this.KeyVal = c} type="text" placeholder="关键字"/>
	    <button onClick={
    
    this.searchHandle}>Search</button>
      </div>
    </section>
    )
  }
}

3-List组件代码

import React, {
    
     Component } from 'react'
import PubSubJs from 'pubsub-js'
import axios from 'axios'
import './index.css'
export default class List extends Component {
    
    
  state = {
    
    
    users: [],
    isFirst: true,
    isLoading: false,
    err: '',
  }

  getSearchFunc = (msg, data) => {
    
    

    console.log('接收的信息', data)
    this.setState({
    
     users: [], isFirst: false, isLoading: true })
    axios
      .get(`https://api.github.com/search/users?q=${
      
      data}`)
      .then(
        (res) => {
    
    
          this.setState({
    
     users: res.data.items, isFirst: false, isLoading: false })
          console.log('请求成功了', res.data)
        },
        (err) => {
    
    
          console.log('请求失败了', err)
          this.setState({
    
    isFirst: false, isLoading: false,err:err.message })
        }
      )
      .catch(() => {
    
    })
  }

  componentDidMount() {
    
    
   this.token = PubSubJs.subscribe('getSearchVal', this.getSearchFunc)
  }

  componentWillUnmount() {
    
    
    PubSubJs.unsubscribe(this.token)
  }

  render() {
    
    
    const {
    
     users, isFirst, isLoading, err } = this.state
    return (
      <div className="row">
        {
    
    isFirst ? (
          <h2>欢迎搜索</h2>
        ) : isLoading ? (
          <h2>Loading...</h2>
        ) : err ? (
          <h3>{
    
    err}</h3>
        ) : (
          users.map((userObj) => {
    
    
            return (
              <div className="card" key={
    
    userObj.id}>
                <a href={
    
    userObj.html_url} target="_blank" rel="noreferrer">
                  <img
                    alt="头像"
                    src={
    
    userObj.avatar_url}
                    style={
    
    {
    
     width: '100px' }}
                  />
                </a>
                <p className="card-text">{
    
    userObj.login}</p>
              </div>
            )
          })
        )}
      </div>
    )
  }
}

4-效果展示

在这里插入图片描述


总结

1- 设计状态时要考虑全面,例如有网络请求的时候要考虑网络延迟和请求失败的状态处理。

2- ES6小知识点:解构赋值 + 重命名

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

3- 消息订阅与发布机制

I. 先订阅,再发布 (一种隔空对话的感觉)

II. 适用于任意组件的通信

III. 要在组件componentWillUnmount生命钩子中取消订阅

4- 扩展fetch发送请求(关注分离的设计思想)

async func () {
    
    
    try {
    
    
        const res = await fetch('url')
        const data = await res.json()
        console.log(data)
    } catch(error) {
    
    
        console.log(error)
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36362721/article/details/130148679
今日推荐