0303github搜索案例-react应用

1 前言

学习了脚手架配置axios,我们通过访问github的接口来做个练习。实例效果如下所示:

0303github搜索案例-react应用_第1张图片

搜索框输入github用户名关键字,点击搜索,列表展示对应的头像和用户名,点击跳转github主页。

基于我们访问github访问慢或者根本打不开的情况,我们通过nodejs,简单的写了个后端服务,代码1-1如下:

const express = require("express")
const axios = require("axios")
const app = express()


/*
  请求地址: http://localhost:3000/search/users?q=aa

  后台路由
    key: /search/users
    value: function () {}
*/
app.get("/search/users", function (req, res) {
  const {q} = req.query
  axios({
    url: 'https://api.github.com/search/users',
    params: {q}
  }).then(response => {
    res.json(response.data)
  })
})

app.get("/search/users2", function (req, res) {
  res.json({
    items: [
      {
        login: "yyx990803",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 1,
      },
      {
        login: "ruanyf",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 2,
      },
      {
        login: "yyx9908032",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 3,
      },
      {
        login: "ruanyf2",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 4,
      },
      {
        login: "yyx9908033",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 5,
      },
      {
        login: "ruanyf3",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 6,
      },
      {
        login: "yyx9908034",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 7,
      },
      {
        login: "ruanyf4",
        html_url: "https://github.com/ruanyf",
        avatar_url: "https://avatars2.githubusercontent.com/u/905434?s=460&v=4",
        id: 8,
      },
      {
        login: "yyx9908035",
        html_url: "https://github.com/yyx990803",
        avatar_url:
          "https://avatars3.githubusercontent.com/u/499550?s=460&u=de41ec9325e8a92e281b96a1514a0fd1cd81ad4a&v=4",
        id: 9,
      },
    ],
  });
});



app.listen(5000, "localhost", (err) => {
  if (!err){
  	console.log("服务器启动成功")
  	console.log("请求github真实数据请访问:http://localhost:5000/search/users")
  	console.log("请求本地模拟数据请访问:http://localhost:5000/search/users2")
  } 
  else console.log(err);
})

  • 如果正常访问github接口https://api.github.com/search/users网络延迟高或者打不开,可以切换为我们模拟的接口。

2 静态组件

2.1 静态页面和样式

页面简单的包含搜索组件和列表展示组件,静态html和css代码如下2-1所示:

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
  <link rel="stylesheet" href="./bootstrap.css">
  <link rel="stylesheet" href="./index.css">
head>
<body>
<div id="app">
  <div class="container">
    <section class="jumbotron">
      <h3 class="jumbotron-heading">Search Github Usersh3>
      <div>
        <input type="text" placeholder="enter the name you search"/> <button>Searchbutton>
      div>
    section>
    <div class="row">
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        a>
        <p class="card-text">reactjsp>
      div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        a>
        <p class="card-text">reactjsp>
      div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        a>
        <p class="card-text">reactjsp>
      div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        a>
        <p class="card-text">reactjsp>
      div>
      <div class="card">
        <a href="https://github.com/reactjs" target="_blank">
          <img src="https://avatars.githubusercontent.com/u/6412038?v=3" style='width: 100px'/>
        a>
        <p class="card-text">reactjsp>
      div>
    div>
  div>
div>
body>
html>

样式使用bootstrap的样式,我们直接放入public\css下面,在主页index.html引入

我们自定义的样式,自定义样式代码如下:

.album {
  min-height: 50rem; /* Can be removed; just added for demo purposes */
  padding-top: 3rem;
  padding-bottom: 3rem;
  background-color: #f7f7f7;
}

.card {
  float: left;
  width: 33.333%;
  padding: .75rem;
  margin-bottom: 2rem;
  border: 1px solid #efefef;
  text-align: center;
}

.card > img {
  margin-bottom: .75rem;
  border-radius: 100px;
}

.card-text {
  font-size: 85%;
}

2.2 静态组件

使用脚手架创建项目后,去除不需要的文件,其中public/css 下放置bootstrap.css,在index.html中引入,代码如下所示:

DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
  <link rel="stylesheet" href="./css/bootstrap.css">
  <title>React 脚手架title>
head>
<body>
  <div id="root">div>
body>
html>

src目录下创建2个组件:

  • Search组件:对应页面搜索部分;
  • List组件:对应列表展示部分。

App.jsx代码2.2-2如下所示:

import React, { Component } from 'react'
import './app.css'
import Search from './component/Search'
import List from './component/List'


export default class App
  extends Component {

  render() {

    // const { githubUsers } = this.state

    return (
      
) } }

Seach组件初始状态代码2.2-3如下所示:

import React, { Component } from 'react'

export default class Search extends Component {

  render() {

    return (
      

搜索github用户

 
) } }

List组件初始状态代码2.2-4如下所示:

import React, { Component } from 'react'

export default class List extends Component {
  render() {
    const { isFirst, isLoading, githubUsers, err } = this.props
    return (
      
avatar

xxx

avatar

xxx

avatar

xxx

) } }
  • 修改类名和样式以后不在提示

3 axios请求github接口

我们自定义样式,都是些的List组件的样式,我们直接把样式放置在List对应的组件处,List组件引入样式。

流程梳理:search请求github接口,返回数据;把数据传递给List组件用于展示。

Search组件和List组件属于兄弟组件,传值目前我们需要通过其父组件App来传递。

第一步:App组件初始化用户数组状态

  state = { 
    githubUsers: [], // 初始化状态,github用户
  } 

第二步:Search请求后端接口,后端请求github接口返回数据;数据返回后,把数据传递给App。代码3-2如下所示:

// Search组件
import React, { Component } from 'react'
import axios from 'axios'

export default class Search extends Component {

  search = () => {
    // 获取用户输入
    const {keyElement: {value: keyword}} = this
    // 发起网络请求
    axios.get(`/api1/search/users?q=${keyword}`).then(
      resp => {
        // console.log('请求成功',resp.data);
        const data = resp.data.items.map(item => {
          return {id: item.id, avatar: item.avatar_url, homePage: item.html_url, username: item.login}
        })
        this.props.updateAppState(data)
      },
      error => {
        // console.log('请求失败', err);
      }
    )
  }
  
  render() {

    return (
      

搜索github用户

this.keyElement = c} type="text" placeholder="输入用户名" /> 
) } } // App组件 /** * 更新用户状态数据 * @param {object} githubUsers */ updateAppState = (githubUsers) => { // 更新用户 this.setState({githubUsers}) }

第三步:App把数据传递给List,展示数据,代码3-3如下所示

// App 组件

// List 组件
render() {
    const { isFirst, isLoading, githubUsers, err } = this.props
    return (
      
{ githubUsers.map(item => { return (
avatar

{item.username}

) }) }
) }

第四步:配置代理,setupProxy.js代码3-4如下

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

module.exports = function (app) {
  app.use(
    createProxyMiddleware("/api1",{
      target: "http://localhost:5000", //配置转发目标地址(能返回数据的服务器地址)
      changeOrigin: true, //控制服务器接收到的请求头中host字段的值
      pathRewrite: { "^/api1": "" }, 
    })
  )
}

4 优化案例

虽然点击搜索能实现效果了但是,存在一些问题:

  • 列表初始需要展示欢迎或者提示信息;
  • 当开始请求后,数据未返回前,展示加载信息;
  • 数据请求成功后,展示用户信息;数据请求失败,展示错误信息。

这时候我们需要拓展App中的状态数据如下所示:

  state = { 
    githubUsers: [], // 初始化状态,github用户
    isFirst: true, // 是否第一次打开页面
    isLoadign: false, // 数据是否加载中
    err: '', // 存储相关的错误信息
  } 

Search组件相应的做出调整如下:

  search = () => {
    // 获取用户输入
    const {keyelement: {value: keyword}} = this
    // console.log(keyword);
    // 发送请求前通知App更新状态
    this.props.updateAppState({isFirst: false, isLoading: true})
    // 发起网络请求
    axios.get(`/api1/search/users?q=${keyword}`).then(
      resp => {
        // console.log('请求成功',resp.data);
        const data = resp.data.items.map(item => {
          return {id: item.id, avatar: item.avatar_url, homePage: item.html_url, username: item.login}
        })
        this.props.updateAppState({isLoading: false, githubUsers: data})
      },
      error => {
        // console.log('请求失败', err);
        this.props.updateAppState({isLoading: false, err: error.message})
      }
    )
  }

List组件展示根据数据,调整展示如下:

render() {
    const { isFirst, isLoading, githubUsers, err } = this.props
    return (
      
{ isFirst ?

欢迎使用,输入github用户名,点击搜索

: isLoading ?

Loading......

: err ?

{err}

: githubUsers.map(item => { return (
avatar

{item.username}

) }) }
) }

关于脚手架设置代理请求真实网络数据小案例,讲解完毕。我们之前兄弟之间传递数据非常的麻烦,下面我们将要学习消息发布和订阅来解决这个问题。

结语

❓QQ:806797785

⭐️源代码仓库地址:https://github.com/gaogzhen/react-staging.git

参考:

[1]React视频教程[CP/OL].2020-12-15.p65-66.

[2]React官网[CP/OL].

[2]ChatGPT[CP/OL].

你可能感兴趣的:(#,React,react.js,javascript,前端)