开心多米诺 發表於 2019-5-26 15:38:00

react前后端对接(axios)

<h4 id="全局配置">全局配置</h4>
<pre><code>1安装axios   npm install axios -S   

2安装cookie    npm install react-cookies -S

3src文件目录下新建文件夹api

4api 下新建statecode.js//该页面用来返回请求状态
export default{
    "-1": "系统繁忙",
    "0": "请求成功",
    "1001":        "资源已存在",
    "1002":        "参数错误",
    "1003":        "两次密码不一致",
    "1004":        "手机号错误",
    "1005":        "邮箱格式错误",
}

5api下新建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,
}

7api下新建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)=&gt;{//登录接口不需要请求头,不仅如此,请求头里的cookie还是由登陆接口的获取的,存储下来后给其他接口使用
                return res.data;
            }).catch((error)=&gt;{
                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)=&gt;{
                return res.data;
            }).catch((error)=&gt;{
                message.error("服务器出错")
            })
      },

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

      //***获取产品列表 (GET)***
      async productListGetApi(params){
            return await axios.get(`${base}/api/product`,{
                params,
                headers:{
                  "token":cookie.load("usertoken")
               }
            }).then((res)=&gt;{
                return res.data
            }).catch((error)=&gt;{
                message.error("服务器出错")
            })
      },
   
      //***删除产品 (DELETE) ***
      async productDeleteApi(params){
            return await axios.delete(`${base}/api/product/${params.id}`,{   //删除接口需要获取当前数据的id才可进行删除
                params,
                headers:{
                  "token":cookie.load("usertoken"),
                }
            }).then((res)=&gt;{
                return res.data
            }).catch((error)=&gt;{
                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)=&gt;{
                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()=&gt;{
      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)   //如果请求失败,在这里打印状态码告诉程序员错误原因
            return;
      }
    }

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

    //***修改密码接口***
    passwordChange=async()=&gt;{
      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);
            return;
      }
    }

    //***获取产品列表接口***
    componentWillMount=async()=&gt;{//在页面渲染完毕之前就执行
      this.productListGet();
    }
   
    //***页码改变***
    onChangePage=(page=1,pageSize=20)=&gt;{
      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);
      }
      this.setState(this.state);   //再获取到数据后,重新渲染页面将数据展示出来
    }

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

    //***修改产品信息***
    modifyProduct=async()=&gt;{
      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);
            return;
      }


}
</code></pre>
<h4 id="读懂接口文档">读懂接口文档</h4>
<pre><code>
/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直接写上去就可以

</code></pre>
<h4 id="参数问题">参数问题</h4>
<pre><code>request&lt;T = any&gt;(config: AxiosRequestConfig): AxiosPromise&lt;T&gt;;   //request 一个参数config
get&lt;T = any&gt;(url: string, config?: AxiosRequestConfig): AxiosPromise&lt;T&gt;;//get两个参数 url config
delete(url: string, config?: AxiosRequestConfig): AxiosPromise;//delete两个参数url config
head(url: string, config?: AxiosRequestConfig): AxiosPromise;   //head两个参数 url config
post&lt;T = any&gt;(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise&lt;T&gt;;//post 三个参数 url data config
put&lt;T = any&gt;(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise&lt;T&gt;; // put 三个参数 url data config
patch&lt;T = any&gt;(url: string, data?: any, config?: AxiosRequestConfig): AxiosPromise&lt;T&gt;; // 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)=&gt;{
                      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)=&gt;{
            return res.data;
      });
    },
}
注意:需要的参数,一个都不少,data如果不需要传,设置为{}都行,也不能不传

</code></pre>
<h4 id="受控组件和不受控组件">受控组件和不受控组件</h4>
<pre><code>在HTML中,&lt;textarea&gt; 的值是通过子属性设置的。在React中,需要通过value设置。我们可以通过添加事件属性onChange监听内容的变化,onChange会在下列情况下被触发:
input或者textarea的内容改变
input的checked状态改变
select的状态改变

【受控组件】
设定了value的input就是一个受控组件。input里会一直展现这个值,用户的任何输入都是无效的。如果你想随着用户的输入改变,使用onChange事件,或者将value改为defaultValue

【非受控组件】
value没有值或者值设为null的input是一个不受控组件。用户的任何输入都会反映到输入框中
这个时候也可以监听onChange事件,内容的改变也会触发事件。
可以通过defaultValue给input设置默认值
</code></pre>
<h4 id="关于formdata传参一般用于文件图片上传以及登录注册等表单信息这种">关于FormData传参(一般用于文件,图片上传以及登录注册等表单信息这种)</h4>
<pre><code>由于axios默认发送数据时,数据格式是Request Payload,而并非我们常用的Form Data格式,后端未必能正常获取到,所以有时我们需要改用FormData方式发送数据
未改用之前
async postPersonInfo(params){
      return axios.post(`${base}/api/auth/realname`,params,{
            headers:{
                "token":cookie.load("usertoken")
            }
      }).then((res)=&gt;{
            return res.data;
      }).catch((error)=&gt;{
            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)=&gt;{
            return res.data;
      }).catch((error)=&gt;{
            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=&gt;{
         
                if(res.code == 200){
                  alert('提交成功');
                     this.$router.push({ path: "/Profit" });

                }else{
                  alert("请输入完整再提交");
                }

            })   
   }

详细见:https://www.jianshu.com/p/bcf19f69ee4f

注:应用场景,只要是请求一般均可使用,但目前我所使用的情况是在写图片等文件相关接口的时候
</code></pre>
<h4 id="请求时加入时间戳">请求时加入时间戳</h4>
<pre><code>确保了请求不会在它第一次被发送后即缓存,而是会在此方法每次被调用后重新创建和重发
verifyImgGet=async()=&gt;{
      this.setState({
            verifyImg:`${base}/api/verifycode/image?time=${new Date().getTime()}`
      })
    }

者也可以加一个随机数:

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

</code></pre>
<h4 id="利用proxy解决跨域问题">利用proxy解决跨域问题</h4>
<pre><code>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)=&gt;{
                return res.data
            }).catch((error)=&gt;{
                message.error("服务器出错")
            })
      },

6、重新启动(必要的,切记每次改动proxy都应该重启项目)

原理:请求接口:请求地址--&gt; 抛给proxy--&gt;proxy处理跨域请求--&gt;完成
proxy扮演一个代理的角色,您不能处理跨域问题,但他可以,所以你把请求发给他,他帮你处理。
</code></pre><br><br>
来源:https://www.cnblogs.com/huihuihero/p/10926228.html
頁: [1]
查看完整版本: react前后端对接(axios)