spring boot+iview 前后端分离架构之首页面包屑的实现(二十一)

spring boot 与 iview 前后端分离架构之首页面包屑的实现(二十一)

  • 公众号
  • 首页面包屑

公众号

在这里插入图片描述
大家可以直接微信扫描上面的二维码关注我的公众号,然后回复【bg21】 里面就会给到源代码的下载地址同时会附上相应的视频教程,并定期在我的公众号上给大家推送相应的技术文章,欢迎大家关注我的公众号。

首页面包屑

前面二十章我们已经基本实现了前端的几个大模块的整合开发,但是在细节部分我们还是有缺失的,比如我们的面包屑、左侧菜单、顶部菜单,这些现在都是在代码里面写死的,这些我们应该是根据具体的场景来动态可配置的。
spring boot+iview 前后端分离架构之首页面包屑的实现(二十一)_第1张图片
因此本章开始分别对以下的几块进行改造,首先本章我们将开始改造我们的面包屑导航,首先我们需要改造我们的router,原先我们的router是没有做拦截的,因此我们做了如下改造,创建一个名为router.js的文件代码如下:

import main from '../view/main/main.vue';


export default [
  {
    path: '/login',
    name: 'login',
    component: resolve => {
      require(['../view/login/login.vue'], resolve);
    }
  },
  {
    path: '/main',
    name: 'main',
    meta: {
      icon: 'ios-settings',
      title: '系统首页',
      hideInMenu: true,
      requireAuth: false //表示当前响应的请求是否需要进行登录拦截验证【true:需要;false:不需要】
    },
    component: resolve => {
      require(['../view/main/main.vue'], resolve);
    }
  },
  {
    path: '/sys',
    name: 'sys',
    component: main,
    meta: {
      icon: 'ios-construct',
      title: '系统管理',
      code:'system-manage',
      requireAuth: true //表示当前响应的请求是否需要进行登录拦截验证【true:需要;false:不需要】
    },
    children:[
      {
        path: 'dictList',
        name: 'dictList',
        meta: {
          icon: 'ios-paper',
          title: '字典维护',
          code:'system-manage-dict',
          requireAuth: true //表示当前响应的请求是否需要进行登录拦截验证【true:需要;false:不需要】
        },
        component: resolve => {
          require(['../view/sys/dict/dictList.vue'], resolve);
        }
      },
      {
        path: 'treeList',
        name: 'treeList',
        meta: {
          icon: 'md-git-network',
          title: '菜单管理',
          code:'system-manage-tree',
          requireAuth: true //表示当前响应的请求是否需要进行登录拦截验证【true:需要;false:不需要】
        },
        component: resolve => {
          require(['../view/sys/tree/treeList.vue'], resolve);
        }
      },
      {
        path: 'roleList',
        name: 'roleList',
        meta: {
          icon: 'ios-cog',
          title: '角色管理',
          code:'system-manage-role',
          requireAuth: true //表示当前响应的请求是否需要进行登录拦截验证【true:需要;false:不需要】
        },
        component: resolve => {
          require(['../view/sys/role/roleList.vue'], resolve);
        }
      },
      {
        path: 'orgList',
        name: 'orgList',
        meta: {
          icon: 'ios-people',
          title: '用户组织',
          code:'system-manage-user',
          requireAuth: true //表示当前响应的请求是否需要进行登录拦截验证【true:需要;false:不需要】
        },
        component: resolve => {
          require(['../view/sys/user/orgList.vue'], resolve);
        }
      }
    ]
  }
]

接着在lib目录底下增加一个util.js的工具类代码如下:

let util = {

};
util.title = function(title) {
  title = title ? title  : 'iView project';
  window.document.title = title;
};

export const forEach = (arr, fn) => {
  if (!arr.length || !fn) return;
  let i = -1;
  let len = arr.length;
  while (++i < len) {
    let item = arr[i];
    fn(item, i, arr);
  }
};

/**
 * 获取当前登陆的用户的权限集合数据
 * @param list {Array} 所有的路由集合数据
 * @param access {Array} 当前允许登陆的路由集合数据
 */
export const getLoginMenuList = (list, access) =>{
  let res = [];
  forEach(list, item => {
    if (!item.meta || (item.meta && !item.meta.hideInMenu)) {
      let obj = {
        icon: (item.meta && item.meta.icon) || '',
        name: item.name,
        meta: item.meta,
        code: item.code,
        path: item.path
      };
      if(hasChild(item)&&showThisMenuEle(item,access)){
        obj.children = getLoginMenuList(item.children, access);
      }
      if (showThisMenuEle(item, access)) res.push(obj);
    }
  })
  return res;
};

const showThisMenuEle = (item, access) => {
  let code = item.meta.code;
  if(access.indexOf(code)!=-1){
     return true;
  }else{
    return false;
  }
}

export const hasChild = (item) => {
  return item.children !=undefined && item.children.length !== 0
};

/**
 * @param {Array} routeMetched 当前路由metched
 * @returns {Array}
 */
export const getBreadCrumbList = (routeMetched, homeRoute) => {
  let res = routeMetched.filter(item => {
    return item.meta === undefined || !item.meta.hide
  }).map(item => {
    let obj = {
      icon: (item.meta && item.meta.icon) || '',
      name: item.name,
      meta: item.meta
    };
    return obj
  });
  res = res.filter(item => {
    return !item.meta.hideInMenu
  });
  return [Object.assign(homeRoute, { to: homeRoute.path }), ...res];
};

/**
 * @param {Array} routers 路由列表数组
 * @description 用于找到路由列表中name为home的对象
 */
export const getHomeRoute = routers => {
  let i = -1;
  let len = routers.length;
  let homeRoute = {};
  while (++i < len) {
    let item = routers[i];
    if (item.children && item.children.length) {
      let res = getHomeRoute(item.children);
      if (res.name) return res;
    } else {
      if (item.name === 'home') homeRoute = item;
    }
  }
  return homeRoute;
};

export default util;

接着我们在修改router里的index.js代码如下:

import Vue from 'vue';
import iView from 'iview';
import Util from '../lib/util';
import VueRouter from 'vue-router';
import routers from './router';

Vue.use(VueRouter);

// 路由配置
const RouterConfig = {
  //mode: 'history',
  routes: routers
};

export const router = new VueRouter(RouterConfig);

router.beforeEach((to, from, next) => {
  iView.LoadingBar.start();
  Util.title(to.meta.title);
  if (to.meta.requireAuth) {
    console.log('需要权限,暂时放开!');
    next();
  } else {
    next();
  }
});

router.afterEach((to) => {
  iView.LoadingBar.finish();
  window.scrollTo(0, 0);
});

最后我们修改main.js,修改完成以后的代码如下:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import {router} from './router/index'
// 引入国际化包
import i18n from './local'
import iView from 'iview'
import 'iview/dist/styles/iview.css'
import runConfig from './config/run.config';
import iviewArea from 'iview-area';

Vue.use(iviewArea);

/**
 * 表示当前的应用启动的时候是以mock的方式启动
 */
if(runConfig.runConfig.mock){
  require('./config/mock/mock.js')
}

Vue.config.productionTip = false
// 引入view的国际化
Vue.use(iView, {
  i18n: (key, value) => i18n.t(key, value)
})

// 格式化时间全局通用方法
Vue.prototype.formatDate = function (date, fmt) {
  let o = {
    'M+': date.getMonth() + 1, // 月份
    'd+': date.getDate(), // 日
    'h+': date.getHours(), // 小时
    'm+': date.getMinutes(), // 分
    's+': date.getSeconds(), // 秒
    'S': date.getMilliseconds() // 毫秒
  }
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  for (var k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
    }
  }
  return fmt
}

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  // 国际化初始化
  i18n,
  components: { App },
  template: ''
})

到此处我们就完成了router部分的改造了,这时候大家点击某一个菜单的时候,我们会看到我们的网页的标题已经变了,如下所示:
spring boot+iview 前后端分离架构之首页面包屑的实现(二十一)_第2张图片
接着我们需要引入我们的vuex来进行数据的存储,我们在src目录底下创建一个store目录,接着在store目录底下创建一个module目录,如下所示:
spring boot+iview 前后端分离架构之首页面包屑的实现(二十一)_第3张图片
app.js的代码如下:

import {getBreadCrumbList, getHomeRoute} from '../../lib/util';
import router from '../../router/router';

export default {
  state: {
    breadCrumbList: localStorage.getItem('breadCrumbList') ? JSON.parse(localStorage.getItem('breadCrumbList')) : [],
    homeRoute: getHomeRoute(router)
  },
  getters: {
    breadCrumbList(state, getters, rootState) {
      return rootState.app.breadCrumbList;
    },
  },
  mutations: {
    setBreadCrumb(state, routeMetched) {
      let breadCrumbList = getBreadCrumbList(routeMetched, state.homeRoute);
      state.breadCrumbList = breadCrumbList;
      localStorage.setItem('breadCrumbList', JSON.stringify(breadCrumbList));
    }
  }
}

index.js的代码如下:

import Vue from 'vue';
import Vuex from 'vuex';

import app from './module/app';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    //
  },
  mutations: {
    //
  },
  actions: {
    //
  },
  modules: {
    app
  }
});

接着在我们的main.js中引入我们的store,改造完成以后代码如下:

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import {router} from './router/index'
// 引入国际化包
import i18n from './local'
import iView from 'iview'
import 'iview/dist/styles/iview.css'
import runConfig from './config/run.config';
import iviewArea from 'iview-area';
import store from './store';

Vue.use(iviewArea);

/**
 * 表示当前的应用启动的时候是以mock的方式启动
 */
if (runConfig.runConfig.mock) {
  require('./config/mock/mock.js')
}

Vue.config.productionTip = false
// 引入view的国际化
Vue.use(iView, {
  i18n: (key, value) => i18n.t(key, value)
})

// 格式化时间全局通用方法
Vue.prototype.formatDate = function (date, fmt) {
  let o = {
    'M+': date.getMonth() + 1, // 月份
    'd+': date.getDate(), // 日
    'h+': date.getHours(), // 小时
    'm+': date.getMinutes(), // 分
    's+': date.getSeconds(), // 秒
    'S': date.getMilliseconds() // 毫秒
  }
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  }
  for (var k in o) {
    if (new RegExp('(' + k + ')').test(fmt)) {
      fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
    }
  }
  return fmt
}

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  // 国际化初始化
  i18n,
  store: store,
  components: {App},
  template: ''
})

最后我们改造我们的main.vue页面,改造完成以后代码如下:




最后我们运行我们的项目,这时候我们会看到我们的面包屑会随着我们点击不同的菜单而展示不同的页面。
spring boot+iview 前后端分离架构之首页面包屑的实现(二十一)_第4张图片
到此为止我们就完成了首页面包屑的实现了。
上一篇文章地址:spring boot+iview 前后端分离架构之组织用户的用户的增删改的实现(二十)
下一篇文章地址:spring boot+iview 前后端分离架构之首页菜单栏的实现(二十二)

你可能感兴趣的:(java,spring,boot,vue,iview,spring,boot,与,iview实现前后端分离架构)