zoukankan      html  css  js  c++  java
  • 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扮演一个代理的角色,您不能处理跨域问题,但他可以,所以你把请求发给他,他帮你处理。
    
  • 相关阅读:
    Haskell Interactive Development in Emacs
    Access Java API in Groovy Script
    手工设置Eclipse文本编辑器的配色
    Color Theme of Emacs
    Gnucash的投资记录
    Special Forms and Syntax Sugars in Clojure
    Use w3m as Web Browser
    SSE指令集加速之 I420转BGR24
    【图像处理】 增加程序速度的方法
    TBB 入门笔记
  • 原文地址:https://www.cnblogs.com/huihuihero/p/10926228.html
Copyright © 2011-2022 走看看