前置准备
- 引入axios
npm i axios和pub-subnpm i pubsub-js - 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>
- 加入bootstrap的css文件以及图标
- 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="请输入关键字"/>
<button onClick = {this.search}>搜索</button>
</div>
</section>
)
}
}
<input ref = {c => this.keyWordNode = c} type="text" placeholder="请输入关键字"/>
一个输入框,具体的输入内容实时存放在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>
)
}
}