关于vue.js:Vue动态路由加载

/*
  约定:
  通过目录后果生产路由信息
  目录构造如下
  目录1--目录2--目录3--页面
  生成的路由path是: 目录1/目录2/目录3/页面
  如果页面用index.vue命名, path会被截取, 生成: 目录1/目录2/目录3

  举荐的目录层级如下
    业务目录
          --模块目录
                  --页面
  此时生成的path为: 业务目录/模块目录/页面, 同时应用Layout布局(蕴含菜单和导航)

  当path只有一层时, 将不应用Layout布局, 如
  页面目录(home)
        --页面(命名index.vue)

  目录中含有components的文件不会生成路由信息
 */


// 首页不须要Layout
// 重定向
// 404

// views为src下页面所在的目录
// 获取所有的路由信息
let allFiles = []
const contexts = require.context(
  '@/views',
  true,
  /^(?!.*?components).*\.vue$/,
  'lazy',
)
contexts.keys().forEach(file => {
  allFiles.push(file)
})
// console.log('allFiles', allFiles)

import Layout from '@/layout/Layout2'
let routes = []

allFiles.forEach(file => {
  let path = file
    .substring(1)
    .replace('/index.vue', '')
    .replace('.vue', '')
  let name = path.substring(1).replace(/\//g, '-')
  let _filePath = file.replace('./', '')
  let component = loader(_filePath)
  // console.log(path)

  let array = path.split('/')
  // console.log(array.length, path)
  if (array.length < 2) {
    return
  }

  // 目前一层目录不必Layout
  if (array.length === 2) {
    let route = {
      path,
      component,
      name,
    }
    routes.push(route)
    return
  }

  path = path.replace(`/${array[1]}/`, '')
  // fullScreen不加layout
  if (array[1] === 'fullScreen') {
    let route = {
      path: `/fullScreen/${path}`,
      component,
      name,
    }
    routes.push(route)
  } else {
    // 多层目录套用Layout
    let route = {
      path: `/${array[1]}`,
      component: Layout,
      children: [{ path, component, name }],
    }
    routes.push(route)
  }
})

const redirect = [
  // 页面首页重定向
  {
    path: '/',
    redirect: '/home',
  },
  {
    path: '/502',
    redirect: '/fullScreen/502',
  },
  // 404
  {
    path: '*',
    redirect: '/fullScreen/404',
  },
]

// 增加重定向
routes.push(...redirect)

// console.log('routes', routes)

// import(
//   /* webpackChunkName: '[request]' */
//   `@/views/${file}`
// )
function loader(file) {
  return () => import(`@/views/${file}`)
}

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export let router = new Router({
  // mode: 'history',
  scrollBehavior: () => ({ y: 0 }),
  routes: routes,
})
import store from '@/store/index'

router.beforeEach((to, from, next) => {
  // 避免用户手动去清导航的本地存储
  if (!localStorage.getItem('boxCategoryDataLocal')) {
    localStorage.setItem('boxCategoryDataLocal', '21212')
    next({ path: '/' })
    return
  }


  // 当url切换时, 切换上下文, 从url中取出上下文, 并且切换上下文
  let contextName = to.path.split('/')[1]
  if (
    store.getters.allContainers[contextName] &&
    contextName !== store.getters.currentContainer.contextName
  ) {
    store.dispatch('changeContext', contextName)
    next()
    return
  }

  // 一些公共页面如common, 是找到不到对应的container对象的
  // 此时也不会切换上下文, 目前不做任何解决
  next()
})

import { Modal } from 'view-design'
router.onError(error => {
  console.log('发版错误码:', error.message)
  const pattern = /Loading chunk (.)+ failed/g
  const isChunkLoadFailed = error.message.match(pattern)
  if (isChunkLoadFailed) {
    Modal.error({
      title: '提醒',
      content: '网站有更新,请刷新页面',
      okText: '刷新',
      onOk: () => {
        location.reload()
      },
    })
  }
})

// 修复在跳转时push了雷同的地址会报错的问题
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}

【腾讯云】云产品限时秒杀,爆款1核2G云服务器,首年99元

阿里云限时活动-2核2G-5M带宽-40-100G SSD服务器,特惠价86元/年(原价724元/年,限时99元续购三次),速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

You may also like...

发表评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据