fetch使用,包含上传图片到七牛和上传excel到后台,基于v

2020-06-19  本文已影响0人  索哥来了

使用前,初略了解fetch:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API
考虑到fetch的兼容性还不是很好,在不支持fetch的时候调用了 之前封装的axios,可参考之前的文章https://www.jianshu.com/p/f3268f923465
然后直接上代码:

import commonFun from './commonFun'
import { Message } from 'element-ui';
import store from '../store'
import ajax from './ajax'

let baseURL = process.env.VUE_APP_HOST;
let isQiNiu = false;//isQiNiu可以用全局参数是因为,不会同时存在多个接口进行  又是七牛,又不是七牛的
const ajaxParams = {};//存放noLoading,避免被覆盖

const myfetch = (url, params = {}, type = 'get', myConfig = {}) => {
    type = type.toLowerCase();
    if(!window.fetch){
        return ajax[type](url, params, myConfig);
    }

    isQiNiu = ( url == '//up-z2.qiniup.com/'|| 
                url == 'http://up-z2.qiniup.com/' || 
                url == 'https://up-z2.qiniup.com/');

    let config = {
            headers: {
                'token': localStorage.loginToken,
            }
        },
        sendUrl = commonFun.urlHasHttp(url) ? url : baseURL + url;

    // 上传文件 不设置Content-Type, 不是上传文件就设置
    if( !(myConfig.type == 'formData' || isQiNiu) ){
        config.headers['Content-Type'] = 'application/json';//提交的数据类型
    }

    if(type == 'get'){
        if(params){
            for(var i in params){
                sendUrl += (sendUrl.includes('?')?'&':'?') + i + '=' + params[i]
            }
        }
    }else{
        config.body = (myConfig.type == 'formData' || isQiNiu) ? params : JSON.stringify(params);
    }

    ajaxParams[sendUrl] = 0; //没有loading
    if(!myConfig.noLoading){
        ajaxParams[sendUrl] = 1; //有loading
        store.commit('addLoading');
    }
    store.commit('addAjax');


    return new Promise( (resolve, reject) => {
        fetch(sendUrl, {
            ...config,
            method: type,
            mode: 'cors', //跨域
        })
        .then(res => {
            if(res.ok){
                return res.json()
            }
        })
        .then(data => {
            if(ajaxParams[sendUrl] === 1){
                store.commit('subLoading');
            }
            store.commit('subAjax');

            if(data.code === 0 || data.code === '0'){
                cb();
                resolve(data.data);
            }else if(data.code == 10001){
                store.commit('setAjaxMsg', '登录过期');
                cb();
            }else{
                if(isQiNiu){
                    if(data.key){
                        cb();
                        resolve(data);
                    }else{
                        store.commit('setAjaxMsg', '上传七牛失败');
                        cb();
                    }
                }else{
                    if(store.state.ajaxMsg != '登录过期'){
                        store.commit('setAjaxMsg', data.message);
                    }
                    cb();
                }
            }
        })
        .catch(err => {
            // 和axios不一样,fetch请求不管成功失败都会进入上面的函数,进入这里一般是因为data里面没有code,上面判断code而导致“写法错误”进入这里
            console.log(err, JSON.stringify(err));
            if(store.state.ajaxMsg != '登录过期'){
                store.commit('setAjaxMsg', '网络异常,请稍后再试');
            }
            cb();
        })
    })
}

function cb(){
    if(store.state.ajaxNum <= 0 && store.state.ajaxMsg){
        let msg = store.state.ajaxMsg;
        store.commit('setAjaxMsg', '');
        if(msg != '登录过期'){
            Message(msg);
        }else{
            Message({
                message: msg,
                duration: 1000,
                onClose: function(){
                    localStorage.loginToken = '';
                    window.location.href = process.env.VUE_APP_LOGINHOST;
                }
            })
        }
    }
}

export default myfetch;

vuex里面存放的状态:
之所以分成loadingNum和ajaxNum,是因为有的请求可能不加loading

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
    state: {
        loadingNum: 0,

        ajaxMsg: '',//多个请求的时候 只弹一个
        ajaxNum: 0,
    },
    mutations: {
        addLoading: (state) => state.loadingNum += 1,
        subLoading: (state) => state.loadingNum = state.loadingNum > 0?state.loadingNum-1:0,

        setAjaxMsg: (state, msg) => state.ajaxMsg = msg,
        addAjax: (state) => state.ajaxNum += 1,
        subAjax: (state) => state.ajaxNum = state.ajaxNum > 0?state.ajaxNum-1:0,
    },
    actions: {},
});

然后直接使用:

import myfetch from '@/function/fetch'

// get,默认方式get
myfetch('/aaaa', {a: 2,b: 3})
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err);
    })
//post、put、delete
//noLoading 表示没有loading转圈圈,不加这个参数表示是有的
myfetch('/aaaa', {a: 2,b: 3}, 'post', {noLoading: true})
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err);
    })

// 上传excel
<input type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" @change="uploadExcel">
<el-button size="small" type="primary" @click="confirmUpload">确认上传</el-button>

uploadExcel(e){
    let me = this;
    let file = e.target.files[0];

    if(file){
        // console.log(file.name);
        if(!file.name.endsWith('.xlsx')){
            me.$message('仅支持.xlsx文件!');
            e.target.value = '';
            return false;
        }

        let params = new FormData();
        params.append('file', file);
        this.uploadData = params;
    }
},
confirmUpload(){
    let me = this;

    let params = this.uploadData;
    if(!params){
        me.$message('请先上传Excel!')
        return false;
    }

    params.append('aa', 1);// 可以增加其他字段
    let url = '/bbb';

    myfetch(url, params, 'post', {type: 'formData'})
    .then(res => {
        console.log(res)
    })
},

上传图片和上传文件类似,封装方法可查看这篇文章https://www.jianshu.com/p/86fc1ab2112d

上一篇下一篇

猜你喜欢

热点阅读