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

递归流星
• 阅读 1974

前言:一般我们在创建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框架?
这样一来,我们有多个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框架?

四、公用方法的管理
公用方法的管理其实可公用数据的管理差不多的,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框架?
或者微信搜过小程序“知付博客”体验
知付博客官网

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这