美文网首页
vue 技术栈 架子 vue-router axios vuex

vue 技术栈 架子 vue-router axios vuex

作者: 一代码农1970 | 来源:发表于2019-06-12 15:41 被阅读0次

本文是vue技术栈基础架子包含:
1 路由配置
2 vuex使用模块化
3 axios封装
4 element-ui 组件库
5 其他 moment 日期格式化 vuex-persistedstate 解决刷新vuex数据丢失。
目录


微信图片_20190612144350.png

main.js 入口

import Vue from 'vue'
import App from './App'
import 'element-ui/lib/theme-chalk/index.css';
import ElementUI from 'element-ui';
import store from './store' // vuex 中文地址 https://vuex.vuejs.org/zh/guide/
import router from './router' // vue-router 中文地址 https://router.vuejs.org/zh/
import plug from './plug' // 插件 全局指令、方法等

Vue.use(ElementUI);
Vue.use(plug);

Vue.config.productionTip = false;

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

router/index.js 路由配置

import Vue from 'vue'
import Router from 'vue-router'
import store from '../store'

Vue.use(Router)

const router = new Router({
  mode: 'history', // 路由模式 history模式,发布服务器需要后端配合。参考地址 https://router.vuejs.org/zh/guide/essentials/history-mode.html
  routes: [
    {
      path: '/',
      name: 'home',
      component:() => import('@/views/home/home'),
      meta: {
        title: '首页'
      }
    }
  ]
})

// vue-router 全局前置守卫
router.beforeEach((to,from,next)=>{
  // token
  let token = store.state.common.userInfo.token;
  // 设置网页标题
  if(to.meta.title) {
    document.title = to.meta.title;
  }
  // 判断token是否存在
  if(token) {
    next(); // 正常跳转
  } else { // 跳转 登录页面
    if(to.path == "/login") {
      next();
    } else {
      next("/login");
    }
  }
});

export default router 

store/index.js vuex

import Vue from 'vue'
import Vuex from 'vuex'
import createPersistedState from "vuex-persistedstate" // 解决刷新,vuex数据丢失
import common from './modules/common'// 公共的

Vue.use(Vuex)

const store = new Vuex.Store({
  // 解决F5刷新页面vuex数据丢失问题
  plugins: [createPersistedState({ 
      storage: window.localStorage
  })],
  modules: { // vuex 模块化
    common
  }
})

export default store

store/modules/common.js 公共的


const common = {
  state: {
    userInfo: {
      token: 'token'
    }, // 用户信息
  },
  getters: {
    
  },
  actions: {
    // 保存用户信息
    setUserInfo:({commit},userInfo) => {
      commit('SETUSERINFO',userInfo);
    }
  },
  mutations: {
    SETUSERINFO: (state, userInfo) => {
      state.userInfo = userInfo;
    }
  }
}

export default common

api/index.js axios数据交互处理

import {Message, Loading } from 'element-ui'
import axios from 'axios' // axios 中文说明 https://www.kancloud.cn/yunye/axios/234845
import store from '@/store'
import router from '@/router'


let loading = null; // 请求 loading

// token 过期 清除 vuex 用户信息 清除本地缓存
let invalidToken = () => {
  Message({
    message:"登录过期,请重新登录",
    type:'error',
    duration:3000,
    showClose: true,
  })

  //清空 token 和 用户信息
  store.dispatch('setUserInfo', {})

  // 清空所有缓存
  window.localStorage.clear();

  // 跳转登录页面
  router.push({
    name: 'login'
  })
}

// 动态配置 axios  baseURL  根据当前url地址,配置 api 接口。 生产或测试
let baseURL = window.location.href.indexOf('生产环境域名') !== -1 ? '生产api地址' : '测试api地址';

// 创建实例
const service = axios.create({
  baseURL: '', // 请求api地址
  timeout: 30000, // 超时时间 毫秒
  withCredentials: true // 表示跨域请求时是否需要使用凭证
})

// 添加请求拦截器
service.interceptors.request.use(
  config => {
    // loading open
    loading = Loading.service({
      lock: true,
      text: '努力加载中...',
      background: 'rgba(0,0,0,0.7)',
      target: document.querySelector('.loading-area') // 设置加载动画区域
    });

    // vuex 用户信息  token
    let token = store.state.common.userInfo.token;

    // 添加请求头
    if (token) {
      config.headers.Authorization = token;
    }

    return config
  },
  error => {
    loading.close();
    Message({
      message:'请求超时',
      type:'error',
      duration:3000,
      showClose: true,
    })
    return Promise.reject(error)
  }
)

//添加响应拦截器
service.interceptors.response.use(
  response => {
    // loading close
    loading.close();
    return response
  },
  error => {
    // loading close
    loading.close();
    Message({
      message:error.message,
      type:'error',
      duration:3000,
      showClose: true,
    })
    return Promise.reject(error)
  }
)

/* 
  @func
  @desc 后端返回数据 统一处理返回状态码,不同的状态码 执行不同的操作。
  @param {object} a.data 后端返回的数据
  @param {object} a.msg  后端返回的消息
  @param {object} a.code 后端返回的状态码
  @param {func} b Promise 成功回调
  @param {func} c Promise 失败回调
*/
let responseCode = ({data, msg, code}, resolve ,reject) => {
  // data 返回参数 msg 返回消息 code 返回状态
  switch(code) {
    // 请求成功
    case 200:
      // 成功回调
      resolve(data);
      break;
    // 请求被拦截 需要重新登录账号
    case 403:
      invalidToken();
      break;
    // 其他状态
    default:
    Message({
      message:msg,
      type:'error',
      duration:3000,
      showClose: true,
    })

    // 失败回调
    reject({
      data,
      msg,
      code,
    });
  }
}

export default {
  /* 
    @func
    @desc axios get 请求
    @param {string} a 接口地址
    @param {object} b = {} 请求参数
  */
  get(url, params = {}) {
    return new Promise((resolve, reject) => {
      service({
        method: 'get',
        url,
        params,
      }).then(({data}) => {
        responseCode(data, resolve, reject);
      }).catch(err => {
        reject(err);
        console.log(err, '异常')
      })
    })
  },
  /* 
    @func
    @desc axios post 请求
    @param {string} a 接口地址
    @param {object} b = {} 请求参数
  */
  post(url, data = {}) {
    return new Promise((resolve, reject) => {
      service({
        method: 'post',
        url,
        data,
      }).then(({data}) => {
        responseCode(data, resolve, reject);
      }).catch(err => {
        reject(err);
        console.log(err, '异常')
      })
    })
  }
}

plug/index.js 插件 添加指令 实例方法 过滤器等

import axios from '@/api' // 封装的 axios 数据交互
import moment from 'moment' // 日期格式化

/* 
  @func
  @desc 日期格式化
  @param {number} a 时间戳
  @param {string} b 格式
*/
let formatDate = (time, type) => {
  let date = '';

  // 如果传入无效的时间 返回空
  if (!time) {
    return date
  }
  switch(type) {
    // 年月日时分秒
    case 'YYYY-MM-DD HH:mm:ss':
      date = moment(time).format('YYYY-MM-DD HH:mm:ss');
      break;
    // 年月日
    case 'YYYY-MM-DD':
      date = moment(time).format('YYYY-MM-DD');
      break;
      // 时分秒
    case 'HH:mm:ss':
    date = moment(time).format('HH:mm:ss');
    break;
    default:
      console.error('vue-format-date 指令参数type格式错误 YYYY-MM-DD HH:mm:ss 或 YYYY-MM-DD')
  }
  return date;
}

//添加 全局的 指令 过滤器 实例方法等
export default {
  install(Vue, options) {
    // 添加全局过滤器 格式化日期
    Vue.filter('formatDate', function(time, type) {
      return formatDate(time ,type)
    })

    // 添加实例方法 ajax 数据交互
    Vue.prototype.$axios = axios;
  }
}

git地址 https://github.com/html5zs/vue

相关文章

网友评论

      本文标题:vue 技术栈 架子 vue-router axios vuex

      本文链接:https://www.haomeiwen.com/subject/bbklfctx.html