最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • vue-element-admin后台项目总结(一)

    正文概述 掘金(四321)   2021-01-26   642

    项目初始化

    利用vue-cli3进行可视化项目的初始化,参考 blog.csdn.net/qq_40636998…

    目录介绍
    vue-element-admin后台项目总结(一)


    权限路由

    权限路由主要作用是进行权限的认证,不同角色进入到系统给出不同的菜单以及路由,大部分权限路由是通过在router中设置路由拦截器 beforeEach 进行判断Cookie或者Session是否已经存在登录验证的Token,如果有就进行下一步的操作去后端获取路由信息,没有就弹出到登录页。
    需要注意用户的信息和路由都是存储在vuex中,这样刷新页面,都会重新去获取,这样做是解决了在另一端修改了此用户的信息或者权限,本机能及时的更新信息。菜单以及路由都是存储在vuex中进行刷新的。

    router.beforeEach((to, from, next) => {
      const token = store.state.user.token || '';
      if (token) { // 判断是否有token
        if (to.path === '/userlogin/login') {//判断是否跳转到登录页,如果有token把跳转登录页的请求直接重置到主页
          next({
            path: '/'
          });
        } else {
          if (store.getters.username.length === 0) { // 判断当前用户是否已拉取完user_info信息(在vuex中存储了用户信息)
            store.dispatch('user/GetInfo').then(() => { // 拉取用户信息
              store.dispatch('permission/GenerateRoutes').then(() => { // 生成可访问的路由表
                router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表(从vuex中获取)
                next({
                  ...to,
                  replace: true
                }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
              })
            }).catch(err => {
              console.log(err);
            });
          } else {
            next() //当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的全面会自动进入404页面
          }
        }
      } else {
        if (to.path.includes('/userlogin')) {
          next();
        } else {
          next('/userlogin'); // 否则全部重定向到登录页
        }
      }
    });
    

    keep-alive多级缓存

    后台项目中多级缓存是非常常见的,多是用于顶部的导航栏上,路由层级为三级的时候需要做特殊的处理 vue-element-admin后台项目总结(一)

    在需要缓存的router-view上进行keep-alive包裹,cachedView就是需要缓存的路由名称

    <template>
     <keep-alive :include="cachedViews">
         <router-view :key="key"></router-view>
     </keep-alive>
    </template>
    
    <script>
     computed: {
        cachedViews() {
          return this.$store.state.tagsView.cachedViews;
        },
      }
    </script>
    

    在vuex中队需要缓存的页面进行存储,在多级的路由需要将路由的父级路由加入的缓存的cachedViews中,不然无法缓存成功,而且每一个vue页面都需要加上name:""这个属性,以此来识别需要缓存的页面。在清除缓存中需要将缓存中父级页面的名称也清除掉,不然页面还是会有缓存。

    const state = {
      visitedViews: [],
      cachedViews: [],
      cachedViewsParent: []//存储每个路由的父级信息
    }
    const mutations = {
      ADD_VISITED_VIEW: (state, view) => {
        if (state.visitedViews.some(v => v.path === view.path)) return
        state.visitedViews.push(
          Object.assign({}, view, {
            title: view.meta.title || 'no-name'
          })
        )
      },
      ADD_CACHED_VIEW: (state, view) => {
        //多级缓存
        if (state.cachedViews.includes(view.name)) return
        view.matched.map(item => {
          //不缓存首页
          if (item.name.indexOf('home') == -1 && state.cachedViews.indexOf(item.name) == -1) {
            state.cachedViews.push(item.name)
          }
        });
        //不缓存首页
        if (!view.name.includes('home')) {
          state.cachedViewsParent.push({
            name: view.name,
            parent: view.matched.filter(item => item.name.indexOf('home') == -1).map(item => item.name)
          });
        }
    
    
      },
      DEL_VISITED_VIEW: (state, view) => {
        for (const [i, v] of state.visitedViews.entries()) {
          if (v.path === view.path) {
            state.visitedViews.splice(i, 1)
            break
          }
        }
      },
      DEL_CACHED_VIEW: (state, view) => {
        let arr = [];
        state.cachedViewsParent = state.cachedViewsParent.filter(item => item.name != view.name);
        //同级情况下不删除上级路由
        state.cachedViewsParent.map(i => [
          arr.push(...i.parent)
        ]);
        view.matched.map(item => {
          
          if (!arr.includes(item.name)) {
            const index = state.cachedViews.indexOf(item.name)
            index > -1 && state.cachedViews.splice(index, 1)
          }
        })
      },
    
      DEL_OTHERS_VISITED_VIEWS: (state, view) => {
        state.visitedViews = state.visitedViews.filter(v => {
          return v.meta.affix || v.path === view.path
        })
      },
      DEL_OTHERS_CACHED_VIEWS: (state, view) => {
        const index = state.cachedViews.indexOf(view.name)
        if (index > -1) {
          state.cachedViews = state.cachedViews.slice(index, index + 1)
        } else {
          // if index = -1, there is no cached tags
          state.cachedViews = []
        }
      },
    
      DEL_ALL_VISITED_VIEWS: state => {
        // keep affix tags
        const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
        state.visitedViews = affixTags
      },
      DEL_ALL_CACHED_VIEWS: state => {
        state.cachedViews = []
      },
    
      UPDATE_VISITED_VIEW: (state, view) => {
        for (let v of state.visitedViews) {
          if (v.path === view.path) {
            v = Object.assign(v, view)
            break
          }
        }
      }
    }
    
    const actions = {
      addView({
        dispatch
      }, view) {
        dispatch('addVisitedView', view)
        dispatch('addCachedView', view)
      },
      addVisitedView({
        commit
      }, view) {
        commit('ADD_VISITED_VIEW', view)
      },
      addCachedView({
        commit
      }, view) {
        commit('ADD_CACHED_VIEW', view)
      },
    
    
      delView({
        dispatch,
        state
      }, view) {
        return new Promise(resolve => {
          dispatch('delVisitedView', view)
          dispatch('delCachedView', view)
          resolve({
            visitedViews: [...state.visitedViews],
            cachedViews: [...state.cachedViews]
          })
        })
      },
      delVisitedView({
        commit,
        state
      }, view) {
        return new Promise(resolve => {
          commit('DEL_VISITED_VIEW', view)
          resolve([...state.visitedViews])
        })
      },
      delCachedView({
        commit,
        state
      }, view) {
        return new Promise(resolve => {
          commit('DEL_CACHED_VIEW', view)
          resolve([...state.cachedViews])
        })
      },
    
      delOthersViews({
        dispatch,
        state
      }, view) {
        return new Promise(resolve => {
          dispatch('delOthersVisitedViews', view)
          dispatch('delOthersCachedViews', view)
          resolve({
            visitedViews: [...state.visitedViews],
            cachedViews: [...state.cachedViews]
          })
        })
      },
      delOthersVisitedViews({
        commit,
        state
      }, view) {
        return new Promise(resolve => {
          commit('DEL_OTHERS_VISITED_VIEWS', view)
          resolve([...state.visitedViews])
        })
      },
      delOthersCachedViews({
        commit,
        state
      }, view) {
        return new Promise(resolve => {
          commit('DEL_OTHERS_CACHED_VIEWS', view)
          resolve([...state.cachedViews])
        })
      },
      delAllViews({
        dispatch,
        state
      }, view) {
        return new Promise(resolve => {
          dispatch('delAllVisitedViews', view)
          dispatch('delAllCachedViews', view)
          resolve({
            visitedViews: [...state.visitedViews],
            cachedViews: [...state.cachedViews]
          })
        })
      },
      delAllVisitedViews({
        commit,
        state
      }) {
        return new Promise(resolve => {
          commit('DEL_ALL_VISITED_VIEWS')
          resolve([...state.visitedViews])
        })
      },
      delAllCachedViews({
        commit,
        state
      }) {
        return new Promise(resolve => {
          commit('DEL_ALL_CACHED_VIEWS')
          resolve([...state.cachedViews])
        })
      },
      updateVisitedView({
        commit
      }, view) {
        commit('UPDATE_VISITED_VIEW', view)
      }
    }
    export default {
      namespaced: true,
      state,
      mutations,
      actions
    }
    

    当然多级路由的缓存会出现坑,同时打开多个父级路由相同的页面时,关闭清除页面无法成功的去掉路由缓存,把多级路由过滤替换成两级路由,具体可以参照 这个解决方案 segmentfault.com/a/119000003…

    let allChildren = [];
    // 将多级路由转换成为二级路由方便使用keep-alive(找出所有的叶子节点,平展开)
    export const flatAsyncRouter = (routers) => {
        searchchildren(routers)
        return allChildren;
    }
    let searchchildren = (arr) => {
        arr.map(item => {
            if (item.children && item.children.length > 0) {
                searchchildren(item.children)
            } else {
                allChildren.push(item) 
            }
        })
    }
    

    起源地下载网 » vue-element-admin后台项目总结(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元