乐趣区

关于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)
}

退出移动版