文章目錄
- React ajax
- 前置說明
- 常用ajax請求庫
- axios
- 訊息訂閱-發布機制
- Fetch
- 案例——github用戶搜索
React ajax
前置說明
- React 本身只關注于界面, 并不包含發送ajax請求的代碼
- 前端應用需要通過ajax請求與后臺進行互動(json資料)
- react 應用中需要集成第三方ajax庫(或自己封裝)
常用ajax請求庫
- 1、jQuery: 比較重, 如果需要另外引入不建議使用
- 2、axios: 輕量級, 建議使用
- 封裝XmlHttpRequest物件的ajax
- promise風格
- 可以用在瀏覽器端和node服務器端
axios
axios:是對ajax進行了封裝,可以實作異步請求
1、前后端分離:在前端中引入axios.js檔案
2、模塊開發:在專案中安裝axios模塊
axios中常用的方法:
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
GET請求:
-
方式一:
axios({ method: 'get', // 默認請求方式為get url: 'api', params: { // 傳遞引數 key: value }, headers: { // 設定請求頭資訊 key: value } responseType: 'json' }).then(response => { // 請求成功 let res = response.data; console.log(res); }).catch(error => { // 請求失敗, console.log(error); }); -
方式二:
axios.get("api", { params: { // 傳遞引數 key: value }, headers: { // 設定請求頭資訊,可以傳遞空值 key: value } }).then(response => { let res = response.data; // 請求成功 console.log(res); }).catch(error => { // 請求失敗, console.log(error); });
POST請求
-
方式一:
// 注:post請求方法有的要求引數格式為formdata格式,此時需要借助 Qs.stringify()方法將物件轉換為字串 let obj = qs.stringify({ key: value }); axios({ method: 'post', url: 'api', data: obj, // 傳遞引數 headers: { // 設定請求頭資訊 key: value } responseType: 'json' }).then(response => { // 請求成功 let res = response.data; console.log(res); }).catch(error => { // 請求失敗, console.log(error); }); -
方式二:
let data = {key: value}, let headers = { USERID: "", TOKEN: "" }; // 若無headers資訊時,可傳空物件占用引數位置 axios.post("api", qs.stringify(data), { headers }).then(response => {// 請求成功 let res = response.data; console.log(res); }).catch(error => { // 請求失敗 console.log(error); });
Qs的使用:
-
參考cdn或者使用npm、cnpm或者yarn進行插件安裝
-
使用cdn時,默認全域變數為Qs
-
Qs基本方法使用:
- qs.stringify() 方法:將目標資料轉換為 string字串
- qs.parse() 方法:將物件字串格式的資料轉換為 物件格式
訊息訂閱-發布機制
-
工具庫: PubSubJS
-
下載:
npm install pubsub-js --save -
使用:
import PubSub from 'pubsub-js' //引入 PubSub.subscribe('delete', function(data){ }); //訂閱 PubSub.publish('delete', data) //發布訊息
Fetch
-
fetch: 原生函式,不再使用XmlHttpRequest物件提交ajax請求
-
老版本瀏覽器可能不支持
-
GET請求:
fetch(url).then(function(response) { return response.json() }).then(function(data) { console.log(data) }).catch(function(e) { console.log(e) }); -
POST請求:
fetch(url, { method: "POST", body: JSON.stringify(data), }).then(function(data) { console.log(data) }).catch(function(e) { console.log(e) })
案例——github用戶搜索

目錄格式:

代碼檔案:
1、使用axios方法:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="stylesheet" href="./css/bootstrap.css">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js:
import React, { Component } from 'react'
import Search from './components/Search'
import List from './components/List'
export default class App extends Component {
state = { //初始化狀態
users:[], //users初始值為陣列
isFirst:true, //是否為第一次打開頁面
isLoading:false,//標識是否處于加載中
err:'',//存盤請求相關的錯誤資訊
}
//更新App的state
updateAppState = (stateObj)=>{
this.setState(stateObj)
}
render() {
return (
<div className="container">
<Search updateAppState={this.updateAppState}/>
<List {...this.state}/>
</div>
)
}
}
setupProxy.js(配置代理):
const proxy = require('http-proxy-middleware')
module.exports = function(app){
app.use(
proxy('/api1',{ //遇見/api1前綴的請求,就會觸發該代理配置
target:'http://localhost:5000', //請求轉發給誰
changeOrigin:true,//控制服務器收到的請求頭中Host的值
pathRewrite:{'^/api1':''} //重寫請求路徑(必須)
})
)
}
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%;
}
List目錄下的index.jsx:
import React,{Component} from "react";
import './index.css'
export default class List extends Component{
render() {
const {users,isFirst,isLoading,err} = this.props
return (
<div className="row">
{
isFirst ? <h2>歡迎使用,輸入關鍵字,隨后點擊搜索</h2> :
isLoading ? <h2>Loading......</h2> :
err ? <h2 style={{color:'red'}}>{err}</h2> :
users.map((userObj)=>{
return (
<div key={userObj.id} className="card">
<a rel="noreferrer" href={userObj.html_url} target="_blank">
<img alt="head_portrait" src={userObj.avatar_url} style={{width:'100px'}}/>
</a>
<p className="card-text">{userObj.login}</p>
</div>
)
})
}
</div>
)
}
}
Search目錄下的index.jsx:
import React,{Component} from "react";
import axios from 'axios';
export default class Search extends Component{
search=()=>{
//獲取用戶的輸入 連續解構賦值+重命名
const {keyWordElement:{value:keyWord}}=this;
//發送請求前通知App更新狀態
this.props.updateAppState({isFirst: false,isLoading: true})
//發送網路請求
axios.get(`/api1/search/users?q=${keyWord}`).then(
response=>{
this.props.updateAppState({isLoading: false,users: response.data.items})
},
error=>{
this.props.updateAppState({isLoading: false,err:error.message})
}
)
}
render() {
return(
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索github用戶</h3>
<div>
<input ref={c => this.keyWordElement = c} type="text" placeholder="輸入關鍵詞點擊搜索"/>
<button onClick={this.search}>搜索</button>
</div>
</section>
)
}
}
服務器 server.js: 需要先啟動服務器
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.listen(5000, "localhost", (err) => {
if (!err){
console.log("服務器啟動成功")
console.log("請求github真實資料請訪問:http://localhost:5000/search/users")
}
else console.log(err);
})
2、使用pubsub方法:
其余檔案代碼均不變
App.js:
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>
)
}
}
List目錄下的index.jsx:
import React,{Component} from "react";
import PubSub from 'pubsub-js';
import './index.css'
export default class List extends Component{
state = { //初始化狀態
users:[], //users初始值為陣列
isFirst:true, //是否為第一次打開頁面
isLoading:false,//標識是否處于加載中
err:'',//存盤請求相關的錯誤資訊
}
componentDidMount() {
this.token=PubSub.subscribe('msg',(_,stateObj)=>{
this.setState(stateObj);
})
}
componentWillUnmount() {
PubSub.unsubscribe(this.token);
}
render() {
const {users,isFirst,isLoading,err} = this.state
return (
<div className="row">
{
isFirst ? <h2>歡迎使用,輸入關鍵字,隨后點擊搜索</h2> :
isLoading ? <h2>Loading......</h2> :
err ? <h2 style={{color:'red'}}>{err}</h2> :
users.map((userObj)=>{
return (
<div key={userObj.id} className="card">
<a rel="noreferrer" href={userObj.html_url} target="_blank">
<img alt="head_portrait" src={userObj.avatar_url} style={{width:'100px'}}/>
</a>
<p className="card-text">{userObj.login}</p>
</div>
)
})
}
</div>
)
}
}
Search目錄下的index.jsx:
import React,{Component} from "react";
import PubSub from 'pubsub-js';
import axios from 'axios';
export default class Search extends Component{
search=()=>{
//獲取用戶的輸入 連續解構賦值+重命名
const {keyWordElement:{value:keyWord}}=this;
//發送請求前通知List更新狀態
// this.props.updateAppState({isFirst: false,isLoading: true})
PubSub.publish('msg',{isFirst: false,isLoading: true})
//發送網路請求
axios.get(`/api1/search/users?q=${keyWord}`).then(
response=>{
// this.props.updateAppState({isLoading: false,users: response.data.items})
PubSub.publish('msg',{isLoading: false,users: response.data.items})
},
error=>{
// this.props.updateAppState({isLoading: false,err:error.message})
PubSub.publish('msg',{isLoading: false,err:error.message})
}
)
}
render() {
return(
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索github用戶</h3>
<div>
<input ref={c => this.keyWordElement = c} type="text" placeholder="輸入關鍵詞點擊搜索"/>
<button onClick={this.search}>搜索</button>
</div>
</section>
)
}
}
3、使用fetch方法:
App.js:
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>
)
}
}
List目錄下的index.jsx:
import React,{Component} from "react";
import PubSub from 'pubsub-js';
import './index.css'
export default class List extends Component{
state = { //初始化狀態
users:[], //users初始值為陣列
isFirst:true, //是否為第一次打開頁面
isLoading:false,//標識是否處于加載中
err:'',//存盤請求相關的錯誤資訊
}
componentDidMount() {
this.token=PubSub.subscribe('msg',(_,stateObj)=>{
this.setState(stateObj);
})
}
componentWillUnmount() {
PubSub.unsubscribe(this.token);
}
render() {
const {users,isFirst,isLoading,err} = this.state
return (
<div className="row">
{
isFirst ? <h2>歡迎使用,輸入關鍵字,隨后點擊搜索</h2> :
isLoading ? <h2>Loading......</h2> :
err ? <h2 style={{color:'red'}}>{err}</h2> :
users.map((userObj)=>{
return (
<div key={userObj.id} className="card">
<a rel="noreferrer" href={userObj.html_url} target="_blank">
<img alt="head_portrait" src={userObj.avatar_url} style={{width:'100px'}}/>
</a>
<p className="card-text">{userObj.login}</p>
</div>
)
})
}
</div>
)
}
}
Search目錄下的index.js:
import React,{Component} from "react";
import PubSub from 'pubsub-js';
// import axios from 'axios';
export default class Search extends Component{
search=async ()=> {
//獲取用戶的輸入 連續解構賦值+重命名
const {keyWordElement: {value: keyWord}} = this;
//發送請求前通知List更新狀態
// this.props.updateAppState({isFirst: false,isLoading: true})
PubSub.publish('msg', {isFirst: false, isLoading: true})
//發送網路請求
// axios.get(`/api1/search/users?q=${keyWord}`).then(
// response=>{
// // this.props.updateAppState({isLoading: false,users: response.data.items})
// PubSub.publish('msg',{isLoading: false,users: response.data.items})
// },
// error=>{
// // this.props.updateAppState({isLoading: false,err:error.message})
// PubSub.publish('msg',{isLoading: false,err:error.message})
// }
// )
try{
const response = await fetch(`/api1/search/users?q=${keyWord}`)
const data = await response.json()
PubSub.publish('msg', {isFirst: false, users:data.items})
}catch (error){
PubSub.publish('msg', {isLoading: false,err:error.message})
}
}
render() {
return(
<section className="jumbotron">
<h3 className="jumbotron-heading">搜索github用戶</h3>
<div>
<input ref={c => this.keyWordElement = c} type="text" placeholder="輸入關鍵詞點擊搜索"/>
<button onClick={this.search}>搜索</button>
</div>
</section>
)
}
}
案例相關知識點:
-
設計狀態時要考慮全面,例如帶有網路請求的組件,要考慮請求失敗怎么辦
-
ES6小知識點:解構賦值+重命名
let obj = {a:{b:1}} const {a} = obj; //傳統解構賦值 const {a:{b}} = obj; //連續解構賦值 const {a:{b:value}} = obj; //連續解構賦值+重命名 -
訊息訂閱與發布機制(pubsub)
- 先訂閱,再發布(理解:有一種隔空對話的感覺)
- 適用于任意組件間通信
- 要在組件的componentWillUnmount中取消訂閱
-
fetch發送請求(關注分離的設計思想)
try { const response= await fetch(`/api1/search/users2?q=${keyWord}`) const data = await response.json() console.log(data); } catch (error) { console.log('請求出錯',error); }
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/328040.html
標籤:其他
