ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

react-github案例

2021-06-10 18:58:17  阅读:102  来源: 互联网

标签:github List App Component react 案例 axios import


github案例

一 react脚手架配置代理_方法一

需要理解的概念有:

  • axios模块的安装与使用
  • 什么是跨域
  • 跨域的解决方案有哪些
  • proxy的限制有什么

https://cra.docschina.org/docs/proxying-api-requests-in-development

测试代理服务器项目:http://qn.chinavanes.com/test_proxy_server.zip

在package.json中追加如下配置

"proxy":"http://localhost:5000"

说明:

  1. 优点:配置简单,前端请求资源时可以不加任何前缀。
  2. 缺点:不能配置多个代理。
  3. 工作方式:上述方式配置代理,当用Ajax请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)

src/App.js

import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
	render() {
		// 解构赋值
		return <div className='todo-container'></div>;
	}
	componentDidMount() {
		this.getData();
	}
	getData = () => {
		axios.get('/students').then((res) => {
			console.log(res);
		});
	};
}
export default App;

package.json

proxy不能是数组,只能是单一代理地址,不能代理多个。

{
  "name": "hello-react",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "axios": "^0.21.1",
    "nanoid": "^3.1.23",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.0.1"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@babel/plugin-transform-runtime": "^7.14.2",
    "@babel/preset-flow": "^7.13.13"
  },
  "proxy": "http://localhost:5000"
}

二 react脚手架配置代理_方法二

需要理解的概念有:

  • 代理中间件的使用
  1. 第一步:创建代理配置文件

    在src下创建配置文件:src/setupProxy.js
    
  2. 编写setupProxy.js配置具体代理规则:

    const proxy = require('http-proxy-middleware')
    // 默认已经安装,不需要再安装
    
    module.exports = function (app) {
    	app.use(
    		'/demo', //请求前缀,代理服务器只有遇到端口号后面带有/api的请求才会转发给服务器
    		proxy({
    			target: 'http://localhost:5000', //配置真正服务器的地址
    			changeOrigin: true, //该配置写不写无所谓
    			pathRewrite: { '^/demo': '' },
    		})
    	);
    	app.use(
    		'/test', //请求前缀,代理服务器只有遇到端口号后面带有/api的请求才会转发给服务器
    		proxy({
    			target: 'http://localhost:5001', //配置真正服务器的地址
    			changeOrigin: true, //该配置写不写无所谓
    			pathRewrite: { '^/test': '' },
    		})
    	);
    };
    

说明:

  1. 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
  2. 缺点:配置繁琐,前端请求资源时必须加前缀。

src/App.js

import React, { Component } from 'react';
import axios from 'axios';
class App extends Component {
	render() {
		// 解构赋值
		return <div className='todo-container'></div>;
	}
	componentDidMount() {
		this.getData();
	}
	getData = () => {
		axios.get('/demo/students').then((res) => {
			console.log(res);
		});
	};
}
export default App;

三 github搜索案例_静态页面

需要理解的概念有:

  • 组件的拆分
  • 静态资源的引入位置
  • className与style的应用
  • a标签rel='noreferrer’的配合
  • img标签alt属性的设置

静态页面:http://qn.chinavanes.com/users_page.zip

image-20210518190945235

src/App.js

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

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

src/components/Search/index.js

import React, { Component } from 'react';

export default class Search extends Component {
	render() {
		return (
			<section className='jumbotron'>
				<h3 className='jumbotron-heading'>Search Github Users</h3>
				<div>
					<input type='text' placeholder='enter the name you search' />
					&nbsp;<button>Search</button>
				</div>
			</section>
		);
	}
}

src/components/List/index.js

import React, { Component } from 'react';
import './index.css';

export default class List extends Component {
	render() {
		return (
			<div className='row'>
				<div className='card'>
					<a rel='noreferrer' 
            href='https://github.com/reactjs' 
            target='_blank'>
						<img
							src='https://avatars.githubusercontent.com/u/6412038?v=3'
							style={{ width: '100px' }}
							alt='avatar'
						/>
					</a>
					<p className='card-text'>reactjs</p>
				</div>
			</div>
		);
	}
}

src/components/List/index.css

.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%;
}

public/index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8" />
  <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>React App</title>
  <link rel="stylesheet" href="./css/bootstrap.css">
</head>

<body>
  <div id="root"></div>
</body>

</html>

四 github搜索案例_axios发送请求

需要理解的概念有:

  • input对象的获取,ref的三种操作方式:字符串、回调、createRef
  • axios的请求
  • github服务器端开放了cors,所以没有跨域问题

1.回调函数的ref设置应用

src/components/Search/index.js

import React, { Component } from 'react';
import axios from 'axios';

export default class Search extends Component {
	search = () => {
		const {
			keywordElement: { value: keyword },
		} = this; // 解构+赋值别名

		// 关键字可以尝试用`atguigu`
		axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
			(res) => {
				console.log(res);
			},
			(err) => {
				console.log(err);
			}
		);
	};
	render() {
		return (
			<section className='jumbotron'>
				<h3 className='jumbotron-heading'>搜索github用户</h3>
				<div>
					<input ref={(c) => (this.keywordElement = c)} 
					type='text' placeholder='请输入搜索的用户名称' />
					&nbsp;
					<button onClick={this.search}>搜索</button>
				</div>
			</section>
		);
	}
}

2.createRef的ref设置应用

src/components/Search/index.js

import React, { Component } from 'react';
import axios from 'axios';

export default class Search extends Component {
	keyword = React.createRef();

	search = () => {
		const {
			current: { value: keyword },
		} = this.keyword; // 解构+赋值别名

		// 关键字可以尝试用`atguigu`
		axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
			(res) => {
				console.log(res);
			},
			(err) => {
				console.log(err);
			}
		);
	};

	render() {
		return (
			<section className='jumbotron'>
				<h3 className='jumbotron-heading'>搜索github用户</h3>
				<div>
					<input ref={this.keyword} type='text' 
					placeholder='请输入搜索的用户名称' />
					&nbsp;
					<button onClick={this.search}>搜索</button>
				</div>
			</section>
		);
	}
}

五 github搜索案例_展示数据

需要理解的概念有:

  • 属性的传递,数组与函数
  • map与forEach的差异
  • 循环时key的设置

src/App.js

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

class App extends Component {
	state = { users: [] };

	saveUsers = (users) => {
		this.setState({ users });
	};

	render() {
		const { users } = this.state;
		return (
			<div className='container'>
				<Search saveUsers={this.saveUsers} />
				<List users={users} />
			</div>
		);
	}
}
export default App;

src/components/Search/index.js

import React, { Component } from 'react';
import axios from 'axios';

export default class Search extends Component {
	keyword = React.createRef();

	search = () => {
		const {
			current: { value: keyword },
		} = this.keyword; // 解构+赋值别名

		// 关键字可以尝试用`atguigu`
		axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
			(res) => {
				console.log(res);
				this.props.saveUsers(res.data.items);
			},
			(err) => {
				console.log(err);
			}
		);
	};

	render() {
		return (
			<section className='jumbotron'>
				<h3 className='jumbotron-heading'>搜索github用户</h3>
				<div>
					<input ref={this.keyword} type='text' placeholder='请输入搜索的用户名称' />
					&nbsp;
					<button onClick={this.search}>搜索</button>
				</div>
			</section>
		);
	}
}

src/components/List/index.js

import React, { Component } from 'react';
import './index.css';

export default class List extends Component {
	render() {
		const { users } = this.props;
		return (
			<div className='row'>
				{users.map((userObj) => (
					<div className='card' key={userObj.id}>
						<a rel='noreferrer' href={userObj.html_url} 
						target='_blank'>
							<img src={userObj.avatar_url} 
                style={{ width: '100px' }}
                alt='avatar' />
						</a>
						<p className='card-text'>{userObj.login}</p>
					</div>
				))}
			</div>
		);
	}
}

六 github搜索案例_完成案例

需要理解的概念有:

  • 请求的不同状态,加载中,加载完成,加载错误
  • 展开式批量参数传递
  • 解构赋值
  • 三元运算的应用

src/App.js

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

class App extends Component {
	state = {
		users: [],
		isFirst: true, // 是否第一次打开
		isLoading: false, // 是否显示isLoading
		err: '', // 错误提示内容
	};

	updateAppState = (stateObj) => {
		this.setState(stateObj);
	};

	render() {
		return (
			<div className='container'>
				<Search updateAppState={this.updateAppState} />
				<List {...this.state} />
			</div>
		);
	}
}
export default App;

src/components/Search/index.js

import React, { Component } from 'react';
import axios from 'axios';

export default class Search extends Component {
	keyword = React.createRef();

	search = () => {
		const {
			current: { value: keyword },
		} = this.keyword; // 解构+赋值别名

		// 发送请求前通知App更新状态
		this.props.updateAppState({ isFirst: false, isLoading: true });

		// 关键字可以尝试用`atguigu`
		axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
			(res) => {
				// 请求成功以后通知App更新状态
				this.props.updateAppState({ isLoading: false, 
                                   users: res.data.items });
			},
			(err) => {
				// 请求失败以后通知App更新状态
				this.props.updateAppState({ isLoading: false, err: err });
			}
		);
	};

	render() {
		return (
			<section className='jumbotron'>
				<h3 className='jumbotron-heading'>搜索github用户</h3>
				<div>
					<input ref={this.keyword} type='text' 
            placeholder='请输入搜索的用户名称' />
					&nbsp;
					<button onClick={this.search}>搜索</button>
				</div>
			</section>
		);
	}
}

src/components/List/index.js

import React, { Component } from 'react';
import './index.css';

export default class List extends Component {
	render() {
		const { isFirst, isLoading, err, users } = this.props;
		return (
			<div className='row'>
				{isFirst ? (
					<h2>欢迎使用,输入关键字,随后点击搜索</h2>
				) : isLoading ? (
					<h2>Loading...</h2>
				) : err ? (
					<h2 style={{ color: 'red' }}>{err.toString()}</h2>
				) : (
					users.map((userObj) => (
						<div className='card' key={userObj.id}>
							<a rel='noreferrer' href={userObj.html_url} 
                target='_blank'>
								<img src={userObj.avatar_url} 
                  style={{ width: '100px' }} 
                  alt='avatar' />
							</a>
							<p className='card-text'>{userObj.login}</p>
						</div>
					))
				)}
			</div>
		);
	}
}

七 消息订阅与发布技_pubsub

需要理解的概念有:

  • 订阅及发布模式
  • 事件的发布与订阅
  • 生命周期钩子函数
  • 组件的嵌套与层次结构

src/App.js

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

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

src/components/Search/index.js

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

export default class Search extends Component {
	keyword = React.createRef();

	search = () => {
		const {
			current: { value: keyword },
		} = this.keyword; // 解构+赋值别名

		// 发送请求前通知List更新状态
		PubSub.publish('pubsubEvent', { isFirst: false, isLoading: true });

		// 关键字可以尝试用`atguigu`
		axios.get(`https://api.github.com/search/users?q=${keyword}`).then(
			(res) => {
				// 请求成功以后通知List更新状态
				PubSub.publish('pubsubEvent', { isLoading: false, users: res.data.items });
			},
			(err) => {
				// 请求失败以后通知List更新状态
				PubSub.publish('pubsubEvent', { isLoading: false, err: err });
			}
		);
	};

	render() {
		return (
			<section className='jumbotron'>
				<h3 className='jumbotron-heading'>搜索github用户</h3>
				<div>
					<input ref={this.keyword} type='text' placeholder='请输入搜索的用户名称' />
					&nbsp;
					<button onClick={this.search}>搜索</button>
				</div>
			</section>
		);
	}
}

src/components/List/index.js

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, // 是否显示isLoading
		err: '', // 错误提示内容
	};

	componentDidMount() {
		this.psEvent = PubSub.subscribe('pubsubEvent', (_, data) => {
			this.setState(data);
		});
	}

	componentWillUnmount() {
		PubSub.unsubscribe(this.psEvent);
	}

	render() {
		// this.props转成this.state
		const { isFirst, isLoading, err, users } = this.state;
		return (
			<div className='row'>
				{isFirst ? (
					<h2>欢迎使用,输入关键字,随后点击搜索</h2>
				) : isLoading ? (
					<h2>Loading...</h2>
				) : err ? (
					<h2 style={{ color: 'red' }}>{err.toString()}</h2>
				) : (
					users.map((userObj) => (
						<div className='card' key={userObj.id}>
							<a rel='noreferrer' href={userObj.html_url} target='_blank'>
								<img src={userObj.avatar_url} style={{ width: '100px' }} alt='avatar' />
							</a>
							<p className='card-text'>{userObj.login}</p>
						</div>
					))
				)}
			</div>
		);
	}
}

八 fetch发送请求

需要理解的概念有:

  • ajax、axios、fetch之间的差异与区别

1.jQuery ajax

$.ajax({
   type: 'POST',
   url: url,
   data: data,
   dataType: dataType,
   success: function () {},
   error: function () {}
});

优势与不足点:

  • 本身是针对MVC的编程,不符合现在前端MVVM的浪潮
  • 基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案
  • JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)

2.axios

axios({
    method: 'post',
    url: '/user/12345',
    data: {
        firstName: 'Fred',
        lastName: 'Flintstone'
    }
})
.then(function (response) {
    console.log(response);
})
.catch(function (error) {
    console.log(error);
});

优势与不足点:

  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 客户端支持防止CSRF
  • 提供了一些并发请求的接口(重要,方便了很多的操作)

3.fetch

try {
  let response = await fetch(url);
  let data = response.json();
  console.log(data);
} catch(e) {
  console.log("Oops, error", e);
}

优势与不足点:

  • 符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里
  • 更好更方便的写法
  • 更加底层,提供的API丰富(request, response)
  • 脱离了XHR,是ES规范里新的实现方式
    1)fetchtch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
    2)fetch默认不会带cookie,需要添加配置项
    3)fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费
    4)fetch没有办法原生监测请求的进度,而XHR可以

为什么要用axios?

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

  • 从浏览器中创建 XMLHttpRequest
  • 从 node.js 发出 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换JSON数据客户端支持防止CSRF/XSRF

九 总结github搜索案例

需要理解的概念有:

1.拆分静态组件,设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办
2.分析得知:Search组件负责搜索,List组件负责展示,状态要交给App
3.List组件不仅要展示用户信息,还要展示:欢迎词、loading、错误信息
4.在App中设计一个方法:getSearchInfo去更新App的状态,一个一个写太麻烦
5.批量的给List组件传递参数:<List {...this.state}/>
6.在List中用三目运算符进行连续判断,从而决定List组件展示什么
7.先订阅,再发布(理解:有一种隔空对话的感觉)
8.适用于任意组件间通信
rror", e);
}




优势与不足点:

- 符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里
- 更好更方便的写法
- 更加底层,提供的API丰富(request, response)
- 脱离了XHR,是ES规范里新的实现方式
  1)fetchtch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
  2)fetch默认不会带cookie,需要添加配置项
  3)fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费
  4)fetch没有办法原生监测请求的进度,而XHR可以

**为什么要用axios?**

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

- 从浏览器中创建 XMLHttpRequest
- 从 node.js 发出 http 请求
- 支持 Promise API
- 拦截请求和响应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据客户端支持防止CSRF/XSRF

# 九 总结github搜索案例

需要理解的概念有:

1.拆分静态组件,设计状态时要考虑全面,例如带有网络请求的组件,要考虑请求失败怎么办
2.分析得知:Search组件负责搜索,List组件负责展示,状态要交给App
3.List组件不仅要展示用户信息,还要展示:欢迎词、loading、错误信息
4.在App中设计一个方法:getSearchInfo去更新App的状态,一个一个写太麻烦
5.批量的给List组件传递参数:`<List {...this.state}/>`
6.在List中用三目运算符进行连续判断,从而决定List组件展示什么
7.先订阅,再发布(理解:有一种隔空对话的感觉)
8.适用于任意组件间通信
9.componentDidMount中订阅消息,要在组件的componentWillUnmount中进行取消订阅

标签:github,List,App,Component,react,案例,axios,import
来源: https://blog.csdn.net/weixin_57218747/article/details/117789339

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有