react前后端對接(axios)


全局配置

1  安裝axios     npm install axios -S   

2  安裝cookie    npm install react-cookies -S

3  src文件目錄下新建文件夾api

4  api 下新建statecode.js  //該頁面用來返回請求狀態
export default  {
    "-1": "系統繁忙",
    "0": "請求成功",
    "1001":	"資源已存在",
    "1002":	"參數錯誤",
    "1003":	"兩次密碼不一致",
    "1004":	"手機號錯誤",
    "1005":	"郵箱格式錯誤",
}

5  api下新建config.js    //該頁面用來設置請求地址
module.exports = {
    base: "http://demo.port.net:8000"
};

6 api下新建index.js   //該頁面用來引入並暴露相關接口,相當於接口匯總(每配置一個模塊的接口,都要在這里匯總,別忘了)
import codes from './statecode.js';   //狀態碼
import login from './login.js';    //登錄頁面
import product from './product.js';   //產品頁面
import buy from './buy.js';  //購買頁面
 
export default {
    stateCode: codes,
    ...login,
    ...product,
    ...buy,
}

7  api下新建login.js, product.js, buy.js等相關模塊的接口頁面(這里給post,get,delete等每種請求寫一個例子)
import axios from 'axios';  //引入axios
import { base } from "./config.js";  //引入請求地址
import cookie from 'react-cookies';//引入cookie保存登錄信息

import {message} from 'antd';

export default {

        //***登錄 (POST)*** 
        async loginApi(params){   //我習慣在接口命名時,后面加上Api,這樣容易區分
            return await axios.post(`${base}/api/demo/login`,params).then((res)=>{  //登錄接口不需要請求頭,不僅如此,請求頭里的cookie還是由登陸接口的獲取的,存儲下來后給其他接口使用
                return res.data;
            }).catch((error)=>{
                message.error("服務器出錯")
            })
        },


        //***登錄后獲取用戶信息 (GET)***
        async getUserInfoApi(params){
            return await axios.get(`${base}/api/demo/info`,{   //get請求只需要兩個參數,所以params和headers放在了一起
                params,
                headers:{
                    "token":cookie.load("usertoken")   //這里的cookie需要在用戶登陸后,將接口的返回值存進cookie里,例子在第8步里
                }
            }).then((res)=>{
                return res.data;
            }).catch((error)=>{
                message.error("服務器出錯")
            })
        },

        //***修改密碼 (POST)***
        async changePasswordApi(params){
            return await axios.post(`${base}/api/demo/modifycode`,params,{
                headers:{
                    "token":cookie.load("usertoken")
                }
            }).then((res)=>{
                return res.data;
            }).catch((error)=>{
                message.error("服務器出錯")
            })
        },

        //***獲取產品列表 (GET)***
        async productListGetApi(params){
            return await axios.get(`${base}/api/product`,{
                params,
                headers:{
                    "token":cookie.load("usertoken")
                 }
            }).then((res)=>{
                return res.data
            }).catch((error)=>{
                message.error("服務器出錯")
            })
        },
    
        //***刪除產品 (DELETE) ***
        async productDeleteApi(params){
            return await axios.delete(`${base}/api/product/${params.id}`,{   //刪除接口需要獲取當前數據的id才可進行刪除
                params,
                headers:{
                    "token":cookie.load("usertoken"),
                }
            }).then((res)=>{
                return res.data
            }).catch((error)=>{
                message.error("服務器出錯")
            })
        }

        //***修改產品信息 (PUT)***
        async productModify(params){
            return await axios.put(`${base}/api/demo/product/${localStorage.getItem("listid")}/${params.id}`, params,{
                headers:{
                    "token":cookie.load("usertoken")
                }
            }).then((res)=>{
                return res.data;
            });
        },
    
}



8 在相關頁面對接口
    import api from '../../api/index.js';  //引入接口文檔
    import cookie from 'react-cookies'  //在登錄頁面需要引入cookie用來存儲登錄信息,其他頁面不需要
    
    state={

        //登錄接口所需參數
        loginpost:{
            username:"",
            password:"",
            code:"",
        },

        //用戶信息
        userNickname:"",

        //修改密碼接口所需參數
        changePasswordFile:{
            password:"",
            newPass:"",
            repeatPass:"",
            code:"",
        }

        

         //獲取產品列表接口需要的參數
         pluginListFile:{
             isloading:false,
             name:"",
             total:0,
             page:1,
             pageSize:20,
         },
         productList:[],  //從接口獲取到的產品數據    

    }

    //***登錄接口***
    handleLogin=async()=>{
        let {state} =this;
        let {username,password,code}=state.loginpost;
        let data=await api.loginApi({     //這個data是請求回來的數據
            username,    //這里是發送過去的參數
            password,
            code
        })
        if(data.code===0){
            cookie.save('usertoken', data.data)   //登錄接口除了返回code,msg,還會返回一個字段(如這里的data)用來區分每一位用戶,這里將接口返回的data,存儲到cookie里即可
            message.success("登錄成功!",3);
            this.userInfoGet();   //登錄后調用“獲取用戶信息接口”來獲取相關信息如昵稱,頭像,渲染到頁面上
        }else{
            console.log(api.stateCode[data.code])   //如果請求失敗,在這里打印狀態碼告訴程序員錯誤原因
            return;
        }
    }

    //***獲取用戶信息接口***
    async userInfoGet(){
        let res=await api.getUserInfoApi()
        if(res.code===0){
            this.setState({
                userNickname:res.data.nickname
            })
        }else{
            console.log(api.stateCode[res.code]);
        }
    }

    //***修改密碼接口***
    passwordChange=async()=>{
        let {password,newPass,repeatPass,code} =this.state.changePasswordFile;
        let data=await api.changePasswordApi({  
            password,    
            newPass,
            repeatPass,
            code,
        })
        if(data.code===0){
            message.success("密碼修改成功!")
            cookie.remove('usertoken')    //密碼修改成功后,這里清除cookie,讓用戶重新登錄
            this.setState({
                userNickname:"",  //將用戶昵稱重新設為空並渲染到頁面,讓用戶知道自己已登出
            })
        }else{
            console.log(api.stateCode[data.code]);
            return;
        }
    }

    //***獲取產品列表接口***
    componentWillMount=async()=>{  //在頁面渲染完畢之前就執行
        this.productListGet();
    }
    
    //***頁碼改變***
    onChangePage=(page=1,pageSize=20)=>{
        this.setState({
            productListFile:Object.assign(this.state.productListFile,{
                page,pageSize
            })
        })
        this.productListGet();
    }

    async productListGet(){
        this.setState({
            productListFile:Object.assign(this.state.productListFile,{
                isloading:true,
            })
        })
        let res=await api.productListGetApi(this.state.productListFile)
        this.setState({
            productListFile:Object.assign(this.state.productListFile,{
                isloading:false
            })
        });
        if(res.code===0){
            this.state.productList=res.data.data;
            this.state.productListFile.total=res.data.total;
        }else{
            console.log(api.stateCode[res.code]);
        }
        this.setState(this.state);   //再獲取到數據后,重新渲染頁面將數據展示出來
    }

    //***刪除產品接口***
    productDelete=async(productList)=>{
        let data=await api.productDeleteApi({
            id:productList.id,
        })
        if(data.code===0){
            this.onChangePage();
            message.success(`插件${productList.name}刪除成功!`)
        }else{
            message.error(api.stateCode[data.code])
        }
    }

    //***修改產品信息***
    modifyProduct=async()=>{
        let {name,keyword}=this.state;
        let data = await api.productModify({
            id:state.qproductmsg.id,     //因為是修改已經獲取到的信息,所以直接調用前面已經獲取到的qrcodemsg即可
            name,
            keyword,
        })
        if(data.code===0){
            message.success('關鍵二維碼修改成功', 3,);
            this.props.history.goBack();
        }else{
            console.log(api.stateCode[data.code]);
            return;
        }


 }

讀懂接口文檔


/api/wechat/qrcode/:officialId/:qrcodeId  帶冒號,動態數據:`${base}/api/wechat/qrcode/${localStorage.getItem("listid")}/${params.id}`  //這列的:qrcodeId需要使用${params.id}動態寫入,params即數組
/api/wechat/statistics/:officialId/qrcode  不帶冒號,靜態的:`${base}/api/wechat/statistics/${localStorage.getItem("listid")}/qrcode`  //這里的qrcode直接寫上去就可以
 

參數問題

  request<T = any>(config: AxiosRequestConfig): AxiosPromise<T>;   //request 一個參數  config
  get<T = any>(url: string, config?: AxiosRequestConfig): AxiosPromise<T>;  //get  兩個參數 url config
  delete(url: string, config?: AxiosRequestConfig): AxiosPromise;  //delete  兩個參數  url config
  head(url: string, config?: AxiosRequestConfig): AxiosPromise;   //head  兩個參數 url config
  post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>;  //post 三個參數 url data config
  put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>; // put 三個參數 url data config
  patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise<T>; // patch 三個參數 url data config

參數解釋 :url —— 請求地址
                   data——發送給服務器的請求數據
                   config——配置(請求頭等),一般都是固定格式

舉個栗子:
  export default{
        async codeDeisgn(params){                                                 
                return await axios.put(`${base}/api/wechat/code/${localStorage.getItem("listid")}/${params.id}`, params,{  //url data
                          headers:{                         //config  一般都是固定格式
                               "token":cookie.load("usertoken")
                          }
                }).then((res)=>{
                      return res.data;
                });
       },
        async qrcodeExtend(params){
        return axios.post(`${base}/api/wechat/code/${localStorage.getItem('listid')}/${params.id}/extend`,{},{   ////這里data就沒有傳參,而是用{}表示
            headers:{
                "token":cookie.load("usertoken")
            }
        }).then((res)=>{
            return res.data;
        });
    },
  }
注意:需要的參數,一個都不少,data如果不需要傳,設置為{}都行,也不能不傳

受控組件和不受控組件

在HTML中,<textarea> 的值是通過子屬性設置的。在React中,需要通過value設置。我們可以通過添加事件屬性onChange監聽內容的變化,onChange會在下列情況下被觸發:
input或者textarea的內容改變
input的checked狀態改變
select的狀態改變

【受控組件】
設定了value的input就是一個受控組件。input里會一直展現這個值,用戶的任何輸入都是無效的。如果你想隨着用戶的輸入改變,使用onChange事件,或者將value改為defaultValue

【非受控組件】
value沒有值或者值設為null的input是一個不受控組件。用戶的任何輸入都會反映到輸入框中
這個時候也可以監聽onChange事件,內容的改變也會觸發事件。
可以通過defaultValue給input設置默認值

關於FormData傳參(一般用於文件,圖片上傳以及登錄注冊等表單信息這種)

由於axios默認發送數據時,數據格式是Request Payload,而並非我們常用的Form Data格式,后端未必能正常獲取到,所以有時我們需要改用FormData方式發送數據
未改用之前
async postPersonInfo(params){
        return axios.post(`${base}/api/auth/realname`,params,{
            headers:{
                "token":cookie.load("usertoken")
            }
        }).then((res)=>{
            return res.data;
        }).catch((error)=>{
            message.error("服務器錯誤")
        })
    }
改用formData傳數據
async postPersonInfo(params){
        let formData = new FormData();  //以FormData的形式提交,注意FormData的首字母大寫
        formData.append("name",params.id);
        formData.append("version",params.version);
        formData.append('idcard',params.idcard);  
        formData.append('name',params.name);  
        return axios.post(`${base}/api/product/name`,formData,{
            headers:{
                "token":cookie.load("usertoken"),
                'Content-Type':'multipart/form-data',    //設置類型
            }
        }).then((res)=>{
            return res.data;
        }).catch((error)=>{
            message.error("服務器錯誤")
        })
    }


有時設置 withCredentials:true , 表示跨域請求時是否需要使用憑證. 默認為false
authen(event) {
         event.preventDefault();
  
        let formData = new FormData();  
         formData.append('fileUpload1',this.files);  
         formData.append('fileUpload2',this.files2);  
         formData.append('fileUpload3',this.files3); 
         formData.append('uid',this.userID);
         formData.append('name',this.name);

        const instance=axios.create({
          withCredentials: true
         }) 
              
        instance.post('http://pay.m6zf.com/index.php?s=/api/user/approved.html',formData).then(res=>{
           
                if(res.code == 200){
                    alert('提交成功');
                     this.$router.push({ path: "/Profit" });

                }else{
                    alert("請輸入完整再提交");
                }

            })    
     }

詳細見:https://www.jianshu.com/p/bcf19f69ee4f

注:應用場景,只要是請求一般均可使用,但目前我所使用的情況是在寫圖片等文件相關接口的時候

請求時加入時間戳

確保了請求不會在它第一次被發送后即緩存,而是會在此方法每次被調用后重新創建和重發
verifyImgGet=async()=>{
        this.setState({
            verifyImg:`${base}/api/verifycode/image?time=${new Date().getTime()}`
        })
    }

者也可以加一個隨機數:

var url="check.jsp?num="+Math.random();

利用proxy解決跨域問題

1、下載proxy包:npm i http-proxy-middleware -S
2、全局搜素webpackDevServer.config.js 或直接找config/webpackDevServer.config.js 頁面

//proxy,  //將之前的注釋掉
    proxy:{    //加入這段代碼
      "/zzzzz":{   //命名隨意
        "target":"http://106.12.52.123:8080",
        "changeOrigin":true,
        pathRewrite:{
          "^/zzzzz":""
        }
      }
    },

3、src/api/config.js頁面

module.exports={
    //base:"http://106.12.52.123:8080"   //去除此行代碼
    base:"/zzzzz"     //增加此行代碼
}

4、package.json

"proxy":"http://106.12.52.123:8080",   //可以不加

5、接口寫法
async productListGetApi(params){
            return await axios.get(`${base}/api/product`,{     //${base}即表示/zzzzz,而/zzzzz又在proxy里等價於http://106.12.52.123:8080
                params,
                headers:{
                    "token":cookie.load("usertoken")
                 }
            }).then((res)=>{
                return res.data
            }).catch((error)=>{
                message.error("服務器出錯")
            })
        },

6、重新啟動(必要的,切記每次改動proxy都應該重啟項目)

原理:請求接口:請求地址  --> 拋給proxy  -->proxy處理跨域請求  -->完成  
proxy扮演一個代理的角色,您不能處理跨域問題,但他可以,所以你把請求發給他,他幫你處理。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM