教你如何封装灵活高复用的vue框架?

前言:一般我们在创建vue项目的时候比较多的采用官方的vue-cli2脚手架去构建项目,一般来说这种模式创建的项目也不需要过多的配置即可使用,但是有一个痛点就是每个项目都需要重新构建和配置,那有没有一种方式可以省去这些繁琐的过程呢,比如说我们有两个同样的项目,使用的都是vue框架,或者说我们之前配置好的一些项目我们想拿过来直接用。今天我们就聊一聊如何去基于vue构建一套可复用,灵活配置的框架,保证我们在需要使用是直接拿过来就可以用 。

总体来说我们需要考虑三点:
1、接口api的管理
2、路由的管理
3、公用数据的管理
4、公用方法的管理



一、接口api的管理
首先我们说说接口api如何统一的管理起来,在调用的时候能方便快捷,并且能减少http的请求,优化使用体验和节省资源。 目前vue-cli3已经更新使用很长时间了,建议大家使用vue-cli3脚手架去构建项目

我们在封装好axios请求的时候就应该考虑api如何去统一的管理起来,这对项目的优化层面来说非常重要,因为管理api可以很大的减少http的请求来节省服务资源提升响应速度。

例如我们这样做,新建一个api文件,在api文件下新建index.js专门存放后期需要使用到的接口:

import request from '@/request/axios'//这个就是我们封装好的axios文件
var ENV =process.env.NODE_ENV
var Tenv;
ENV=='development'?Tenv='/api':Tenv=''
// 接口封装请求示例
export const getDiaryList = (pageIndex,pageSize) => {
  return request({
    url: Tenv+'/getDiaryList/list',
    method: 'get',
    params: {
        pageIndex:pageIndex,
        pageSize:pageSize,
    }
  })
}

顺便贴上我的axios的封装代码:

/**
 * http配置
 * axios参数说明
 */
import axios from 'axios'
import NProgress from 'nprogress'//这是导航栏的请求状态动画插件,具体见下图
import 'nprogress/nprogress.css'

axios.defaults.timeout = 10000;
//返回其他状态吗
axios.defaults.validateStatus = function (status) {
  return status >= 200 && status <= 500; // 默认的
};
//跨域请求,允许保存cookie
axios.defaults.withCredentials = true;
NProgress.configure({
  showSpinner: false
});
//HTTPrequest拦截
axios.interceptors.request.use(config => {
  NProgress.start();
  const meta = (config.meta || {});
  const isToken = meta.isToken === false;
  //headers中配置serialize为true开启序列化
  return config
}, error => {
  return Promise.reject(error)
});
//HTTPresponse拦截
axios.interceptors.response.use(res => {
  NProgress.done();
  const status = res.data.code || 200;
  const message = res.data.msg || '未知错误';
  if (status !== 200) {
    return Promise.reject(new Error(message))
  }
  return res;
}, error => {
  NProgress.done();
  return Promise.reject(new Error(error));
});

export default axios;

NProgress就是做这个事的,当然不要也可以,因为我这是一个后台管理系统:
教你如何封装灵活高复用的vue框架?-LMLPHP
这样一来,我们有多个api的话可以直接管理起来,或者有多个类型的也可以分文件存放,用的话只需要引入就可以了,因为们发现好多初学者都直接在页面内每次都调用axios.get这样的方式

页面引入api文件:

import {getDiaryList} from '@/api/index'
//可以是一个对象下面有多个

使用:

getDiaryList(pageIndex,pageSize){
    getDiaryList(pageIndex,pageSize).then(res=>{
      // 请求成功处理
      console.log(res.data)
    }).catch(res=>{
      //请求失败处理
      console.log('请求失败')
    })
},

二、路由的管理
为什么要做路由的管理呢,路由可以说是vue的灵魂所在,之前我就接手过一个项目,所有的路由全部在router下index的文件里写着,也没有父子之分,使用查找起来极为不方便。
关于路由的管理,我们可以在router下新建一个文件夹专门去管理路由,比如说这个文件夹名叫RouterPage,我们可以分模块分页面去管理,比如说我们可以在RouterPage下新建一个index.js管理公用、分模块的页面路由,这样在使用上也可以方便很多,管理上也轻松了许多,不至于我们下次交给别人的时候一脸茫然。
比如我们的RouterPage下index.js文件可以是这样的:


/**路由页面配置文件**/
export default [
    { path: "/", redirect: '/index',},
    {
        path: '/index',
        name: '首页',
        component: () => import( '@/views/index'),
        meta: { requireAuth: true},//是否检查登录,
        children:[
            {
                path:'/',
                name:'登录页',
                component: () => import( '@/views/home'),
            },
        ]
    },
    {
        path: '/login',
        name: '登录页',
        component: () => import( '@/views/login'),
        meta: { requireAuth: false}
    },
]

我们在router下的index.js文件直接import再添加路由加可以使用了,在上面RouterPage下的index.js我们可以去配置公用的、模块的等各种路由;

import Vue from 'vue'
import VueRouter from 'vue-router'
import RouterPage from './RouterPage/'//引入我能创建的RouterPage文件名,
Vue.use(VueRouter)
const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
})
router.addRoutes([...RouterPage]);//添加路由
export default router

还有一点我觉的在封装的是肯定会考虑到,项目也肯定会用到,就是检查当前打开的页面用户是否登录、是否需要登录,可以根据路由的全局监测去控制,可以在src目录下新建一个inspect.js文件专门去管理控制:

import router from './router'
import Cookies from 'js-cookie'//操作cookie的插件
router.beforeEach((to, from, next) => {
    //Cookies.set('isAuth', 'iii', { expires: 1 });
    //to.matched.some(record => record.meta.requireAuth)这个就是我们再路由中设置的meta下requireAuth的属性,为true即表示需要判断是否登录,为false就不用判断
    if (to.matched.some(record => record.meta.requireAuth)) {
        if (Cookies.get('isAuth')) { //判断的条件可以自定,我这里是cookie判断,登录了会存储isAuth
          if (to.fullPath == '/login') {

          } else {
            next()
          }
        } else {
          next({
            path: '/login',
            query: { redirect: to.fullPath }
          })
        }
   } else {
        Cookies.remove('isAuth');
        next()
   }
})

然后把这个文件在main.js全局引入就可以了,就可以实现路由变化是监测用户是否登录或者登录是否过期。

三、公用数据的管理
关于公用数据的管理,官方已经提供了一种完美的方法,就是vuex状态数据管理,这个我有一篇文章专门说过如果去使用vuex,不会的可以去看看。
vuex使用教程
当然还有另外一种方法,就是json数据管理方法,这种的话也可以实现本地公用数据的管理,但我还是建议使用官方的vuex。
比如说我们有一个导航,需要去做本地菜单的预配置,我为什么不采用vuex的原因是,有可能我们菜单会有二级三级甚至四级放在vuex里或比较影响数据的直观性,那么我们可以这样做,创建一个nav.config.js:



let results={
    title:'管理平台',
    icon:'el-icon-s-platform',
    tab:[
        {name:'导航1',path:'/index/login','icon':'el-icon-s-check',children:[
            {name:'子集',path:'/','icon':'el-icon-s-check'},
            {name:'子集1',path:'/','icon':'el-icon-s-check'},
            {name:'子集2',path:'/','icon':'el-icon-s-check'},
            {name:'子集3',path:'/','icon':'el-icon-s-check'},
            {name:'子集4',path:'/','icon':'el-icon-s-check'},
        ]},
        {name:'导航7',path:'/index/home','icon':'el-icon-s-check'},
        {name:'用户管理',path:'/index/login','icon':'el-icon-menu',children:[
            {name:'子集1',path:'/','icon':'el-icon-s-check'},
            {name:'子集1',path:'/','icon':'el-icon-s-check'},
            {name:'子集2',path:'/','icon':'el-icon-s-check',children:[
                {name:'子集11',path:'/','icon':'el-icon-s-check'},
                {name:'子集12',path:'/','icon':'el-icon-s-check'},
                {name:'子集23',path:'/','icon':'el-icon-s-check'},
                {name:'子集34',path:'/','icon':'el-icon-s-check'},
                {name:'子集45',path:'/','icon':'el-icon-s-check'},
            ]},
            {name:'子集3',path:'/','icon':'el-icon-s-check'},
            {name:'子集4',path:'/','icon':'el-icon-s-check'},
        ]},
        {name:'导航9',path:'/index/login','icon':'el-icon-s-check'},
        {name:'导航10',path:'/index/login','icon':'el-icon-s-check'}
    ]
}
export default {
  results
}

然后在需要的文件引入或者赋值给vuex的state上:

import navConfig from'../nav.config'
data(){
    return {
        tabResults:navConfig.results,
    }
},

这样我们就可以直接在特定的文件去使用this.tabResults去操作或者页面直接绑定使用了,也是非常的方便,多用于本地菜单的配置,可以灵活管理,如:
教你如何封装灵活高复用的vue框架?-LMLPHP
四、公用方法的管理
公用方法的管理其实可公用数据的管理差不多的,vuex也可以实现,但是我们一般的还是习惯于管理在公用的方法文件中,达到直观、方便、灵活的效果。
比如我们可以新建一个utils.js:



/**
 * 日期格式化
 */
export function dateFormat(date, format) {
  format = format || 'yyyy-MM-dd hh:mm:ss';
  if (date !== 'Invalid Date') {
    let o = {
      "M+": date.getMonth() + 1, //month
      "d+": date.getDate(), //day
      "h+": date.getHours(), //hour
      "m+": date.getMinutes(), //minute
      "s+": date.getSeconds(), //second
      "q+": Math.floor((date.getMonth() + 3) / 3), //quarter
      "S": date.getMilliseconds() //millisecond
    }
    if (/(y+)/.test(format)) format = format.replace(RegExp.$1,
      (date.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (let k in o)
      if (new RegExp("(" + k + ")").test(format))
        format = format.replace(RegExp.$1,
          RegExp.$1.length === 1 ? o[k] :
            ("00" + o[k]).substr(("" + o[k]).length));
    return format;
  }
  return '';
}
/**
 * Json强转为Form类型
 * @param obj
 * @returns {FormData}
 */
export function toFormData(obj) {
  const data = new FormData();
  Object.keys(obj).forEach(key => {
    data.append(key, Array.isArray(obj[key]) ? obj[key].join(',') : obj[key]);
  });
  return data;
}

可以在main.js分别引入或者全部引入
分别引入,只使用一个或多个方法:

import { toFormData } from './utils'

全部引入:

import Utils from './utils'
//使用
Utils.toFormData(obj)

总结:以上呢我们从四个方面说了下如何封装属于自己的可复用的vue框架,比较建议的做法的就是封装好一个保存起来,可以放在阿里code上也可以放在github上,这样我们下次再使用的时候直接dowm下来做基本的代理或者域名配置就可以,能极大的节省很多时间,避免重复的工作。
好了欢迎大家关注我的博客小程序(目前在正在完善),我们一起学历交流,一起进步成长。
教你如何封装灵活高复用的vue框架?-LMLPHP

08-30 17:18