使用消息订阅预发布的方式实现github搜索

323 阅读2分钟

前置准备

  1. 引入axios npm i axios和pub-sub npm i pubsub-js
  2. public里的index
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>react脚手架</title>
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <link rel="stylesheet" href="/css/bootstrap.css">
    <!-- <link rel="stylesheet" href="%PUBLIC_URL%/css/bootstrap.css"> (只适用于React) -->
    <!-- 这个bootstrap可以注掉 -->
</head>
<body>
    <div id="root"></div>
</body>
</html>
  1. 加入bootstrap的css文件以及图标
  2. src里的index
//引入react核心库
import React from 'react'
//引入ReactDOM
import ReactDOM from 'react-dom'
//引入App
import App from './App'
//渲染App组件到root里
ReactDOM.render(<App/>,document.getElementById('root'))

正式开始

新建两个组件 List and Search

Search解析

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

export default class Search extends Component {

    search = ()=>{
        // 获取用户输入(ref)
        const {value} = this.keyWordNode
        PubSub.publish('heybro',{isFirst:false,isLoading:true})
        // 发布消息,点击按钮发送请求前的状态
        axios.get(`http://api.github.com/search/users?q=${value}`).then(
            response =>{PubSub.publish('heybro',{users:response.data.items,isLoading:false})},
            error =>{console.log('失败了',error)}
            // 注意!是反引号``不是''
        )
    }

    render() {
        return (
            <section className="jumbotron">
		<h3 className="jumbotron-heading">搜索github用户</h3>
		<div>
                    <input ref = {c => this.keyWordNode = c} type="text" placeholder="请输入关键字"/>&nbsp;
                    <button onClick = {this.search}>搜索</button>
		</div>
            </section>
        )
    }
}

<input ref = {c => this.keyWordNode = c} type="text" placeholder="请输入关键字"/>&nbsp; 一个输入框,具体的输入内容实时存放在const {value} = this.keyWordNode

<button onClick = {this.search}>搜索</button> 点击触发Search方法

PubSub.publish('heybro',{isFirst:false,isLoading:true}) // 发布消息,点击按钮发送请求前的状态 PubSub.publish发布消息方法,接头暗号是 heybro 改变了两个状态,表示点击按钮正在加载

axios.get(`http://api.github.com/search/users?q=${value}`).then( response =>{PubSub.publish('heybro',{users:response.data.items,isLoading:false})}, error =>{console.log('失败了',error)} // 注意!是反引号``不是'' )

使用axios,把刚刚输入的 value 放在url里,进行一个查询,然后使用publish将查询的结果(response.data.items)赋给users状态,并改变一个状态,另如果请求失败则控制台输出失败了

List解析

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

export default class List extends Component {

	state = {
        users:[], //初始化状态
        isFirst:true, //是否为第一次打开页面
        isLoading:false, //是否加载中
        err:'',//存储错误信息
        } 

      componentDidMount(){
        //该函数大多做一些初始化的事,这里是订阅消息,当发布的是‘heybro’时,接受stateObj对象,并且更新对象
        this.token = PubSub.subscribe('heybro',(_,stateObj)=>{
            this.setState(stateObj)
        })
      }
      
      componentWillUnmount(){
          PubSub.unsubscribe(this.token)
      }

    render() {
        const {users,isFirst,isLoading}=this.state
        return (
            <div className="row">
                {
                isFirst ? <h2>hey,bro!</h2> :
                isLoading ? <h2>Loading</h2> :
                users.map((userObj)=>{ 
                    return(
                        <div key={userObj.id} className="card"> {/* 每个map遍历都要有key值 */}
                        <a href={userObj.html_url} target="_blank">
                          <img alt="Can't find avatar" src={userObj.avatar_url} style={{width: '100px'}}/>
                        </a>
                        <p className="card-text">{userObj.login}</p>
                        </div> 
                    )
                })
                }
            </div>
        )
    }
}

	state = {
        users:[], //初始化状态
        isFirst:true, //是否为第一次打开页面
        isLoading:false, //是否加载中
        err:'',//存储错误信息
        } 

状态里放一个数组和两个是否状态

     componentDidMount(){
        //该函数大多做一些初始化的事,这里是订阅消息,当发布的是‘heybro’时,接受stateObj对象,并且更新对象
        this.token = PubSub.subscribe('heybro',(_,stateObj)=>{
            this.setState(stateObj)
        })
      }

PubSub.subscribe方法表示如果发布的接头暗号是heybro时,先说一句话(这里用下划线代替),然后接受一个stateobj对象,然后用它更新state状态

先解构赋值 const {users,isFirst,isLoading}=this.state

然后对两个状态写两个三目运算符

然后用user数组内置的map方法遍历输出结果,具体方式为:userObj为数组内每一个对象,先设定key值 <div key={userObj.id} className="card">

<a rel="noreferrer" href={userObj.html_url} target="_blank"> 然后用一个a标签包住要显示的内容,以便点击图片进入主页,其中网址href是从obj的html_url属性中取出的,target="_blank"表示带年纪后会在新的空网页中加载

<img alt="Can't find avatar" src={userObj.avatar_url} style={{width: '100px'}}/>然后图片的地址也是从userobj的url取出的,在设定一点style

<p className="card-text">{userObj.login}</p>最后是从obj中获取的用户名

组装组件完成项目

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

export default class App extends Component {

	render() {
		return (
			<div className="container">
			<Search/>
			<List/>
		  </div>
		)
	}
}