在项目中,接口请求是一定会出现的,那么相对的,对接口请求的方法封装也是必要的。

本方法请求使用的aixos插件,

封装:

// src/utils/request.js
// 封装了axios的请求方法,完善请求前后拦截以及加载动画
// router用于路由跳转
// common.js中存放着各种公共方法,和request.js同级目录
// 加载动画Toast使用的是有赞的ui框架vant

import axios from 'axios';
import router from './../router';
import { Toast } from "vant";
import { getToken } from './common.js';

let request = axios.create({
    baseURL: process.env.VUE_APP_BASE_URL, // 获取基础公共路径
    timeout: 10000, // 允许超时时限设置10s
});

// 添加请求拦截器,在请求前做相关操作
request.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    // 此处对数据或接口进行处理判定
    console.log(config);

    // 接口请求判断拦截,如果需要登录信息,添加登录信息
    config.isNeedLogin && (config.data['token'] = getToken());

    // 接口请求统一拦截,如果所有接口都需要该参数,统一添加
    config.data['chnlCode'] = 'BYXLDA';
    config.data['from'] = 'BIYOU';
    config.data['examId'] = '20190007';

    // 加载动画
    Toast.loading({
        duration: 0,
        mask: false,
        forbidClick: true,
        message: '加载中...'
    });

    return config;
}, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
});

// 添加响应拦截器,对获取到的响应统一处理
request.interceptors.response.use(function (response) {
    // 对响应数据做点什么
    // 关闭加载动画
    Toast.clear();

    // 此处对返回状态进行判定,可以处理登陆过期等各种状态。
    if (response.data.code == '0000') {
        return Promise.resolve(response.data.appdata)
    } else if (response.data.code == '3202'){
        // 假定3202错误码,需重新登录
        return router.replace('/login')
    } else {
        return Promise.reject(response.data.msg)
    }
}, function (error) {
    // 对响应错误做点什么
    Toast.clear();

    let errStr = error.toString();
    if (errStr.search('timeout') !== -1) {
        error = '请求超时'
    } else if (errStr.toLocaleLowerCase().indexOf('network error') != -1) {
        error = '网络错误'
    }
    return Promise.reject(error);
});


export {
    request
}


使用:

// src/apis/exam.js
// apis文件夹是放各种请求的

import { request } from "@/utils/request"

export function openRecord(param) {
    return request({
        url: 'exam/openPsych',
        method: 'post',
        data: param,
        isNeedLogin: true
    })
}
// src/view/exam.vue

import {openRecord} from "@/apis/exam";
    

export default {
    name: "tips",
    data() {
        return {
            examId: 'xxx',
            token: 'xxx'
        }
    },
    methods: {
        openPsy() {
            openRecord({
                token: this.token,
                examId: this.examId
            }).then(res => {
                this.$router.replace({
                    path: 'list',
                    query: {
                        examId: this.examId,
                    }
                })
            }).catch(err => {console.log(err)})
        }
    }
}

差不多就是下面这个效果:


然后处理下路由的封装与拦截。本项目中,我需要处理这几种情况:

1.登录页:在微信内授权登录,在微信外手机号登录;

2.其他页面:需要用户处于登录状态才可浏览;

3.分享:只做微信内分享,分享内容所有页面统一,地址统一为登录页(如果遇到需求为分享地址为页面对应地址,需考虑页面逻辑是否能进入,有无前缀进入逻辑,比如我分享的是测试结果页,产品要求的是分享出去的是什么页面,其他人打开也是什么页面,且登录者为打开页面的用户自己,此处就存在矛盾,没有做过题目的人如何获得结果,不过产品应该不会提这种矛盾需求)

先写到这,我要先回家了,等会估计会下雨,先回去再说。

路由的封装与拦截:

// src/router.js
// src/routes  用于放各种路由的文件夹


import Vue from 'vue'
import Router from 'vue-router'
import { isWechatBrowser } from "./utils/util";
import { jssdkConfig } from "@/assets/js/wxShareSDK";
Vue.use(Router);

const router = new Router({
    routes: [
        {
            path: '/',
            name: 'home',
            component: () => import(/* webpackChunkName: "home" */ './views/Home.vue')
        },
        {
            path: '/about',
            name: 'about',
            // route level code-splitting
            // this generates a separate chunk (about.[hash].js) for this route
            // which is lazy-loaded when the route is visited.
            component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
        },
        {
            path: '/tips',
            name: 'tips',
            component: () => import(/* webpackChunkName: "tips" */ './views/Tips.vue')
        }
    ]
});

// 全局变量
// 此处仅为了方便展示放在此处,根据个人习惯可自由处理
// 此全局变量也可以放在.env基础配置中
Vue.prototype.$BASE_VAR = {
    closeWechatShareFunction: false,
    closeQrcodeAlertFunction: false,
    closeAppShareFunction: false,
    hiddenBtnForBack: false,
    hiddenEnterForReport: false, // list页总结果报告入口
    hiddenShareIconBtn: false, // 隐藏所有分享icon
    loginType: 'wechat', // 'wechat, phone, token'
    chnlType: '1'
};

// 一开始就走接口获取全局变量并修改对应逻辑
getChnlGlobalVar(router, Vue.prototype.$BASE_VAR);

router.beforeEach((to, from, next) => {
    if (!Cookies.get('token')) {
        // 如果未登录,跳转到登录页
        // 登录页的类型需要根据渠道以及环境判断
        // 浏览器环境优先级最高,先判断是否在微信内,是的话就微信授权登录
        // 否的话在根据渠道号跳转到对应版本的登陆页
        if (isWechatBrowser()) {
            getWechatCredit();
        } else {
            // 根据渠道号跳转到对应版本的登陆页
            // 可以由前端控制,不过前提是每次增加渠道都需要前端发版本
            // 由后端控制,个人推荐后端控制,通过接口获取该渠道号需要跳转的版本
            switch (Vue.prototype.$BASE_VAR.chnlType) {
                case '1':
                    router.push({
                        path: '/login'
                    });
                    break;
                case '2':
                    router.push({
                        path: '/login2'
                    });
                    break;
            }
        }
    } else {
        next();
    }

});

router.afterEach((to, from) => {
    // 微信分享拦截
    // 调用微信sdk分享,初始值
    let shareParams = {
        title: 'xxx',
        desc: 'xxx',
        imgUrl: 'xxx',
        link: 'xxx'
    };

    shareParamChangeByChnlType(router, shareParams, to);
    jssdkConfig(shareParams);
});


function shareParamChangeByChnlType(router, shareParams, to) {
    // ...
}
function getChnlGlobalVar() {
    // ...
}
function getWechatCredit(callBackUrl) {
    // ...
}

export default router;

 

Logo

前往低代码交流专区

更多推荐