【Vue框架】Vue路由配置

前言

为了看后端权限在前端的使用,阅读vue-element-admin-4.2.1代码来进行理解;同时了解一下前端框架,并对部分内容进行详细介绍(学习)。本文主要从main.js来看各个内容,并整理main,router和store间的关系。

代码下载:vue-element-admin-4.2.1
PS:本文虽然很长,但是其实很简单,代码上已经写好注释,慢慢看

本文介绍的代码目录结构:
【Vue框架】Vue路由配置_第1张图片

1、main.js

1.1 代码

这里主要介绍一些主要内容,css样式和mock等部分都不做说明。

import Vue from 'vue'
import Cookies from 'js-cookie'
import Element from 'element-ui'
import App from './App'
import store from './store'
import router from './router'
import * as filters from './filters' // global filters

// 使用 `Element` 组件库
Vue.use(Element, {
  size: Cookies.get('size') || 'medium' // set element-ui default size
})

// register global utility filters 遍历 `filters` 对象的键值对,全局注册过滤器
Object.keys(filters).forEach(key => {
  Vue.filter(key, filters[key])
})
// 设置生产环境的提示信息为 `false`,避免显示开发环境的提示信息
Vue.config.productionTip = false

// 创建Vue实例
// 请注意,这段代码是Vue.js应用程序的入口文件
new Vue({
  el: '#app', // 将Vue挂载到id为`app`的DOM元素上
  // 配置路由,就是用我们在router目录中写好的index,传入了 `router` 和 `store` 对象作为参数  
  router, // 路由实例
  store, // 状态管理实例
  render: h => h(App) // 用于渲染根组件,`App` 组件是根组件,渲染`App`组件
})

1.2 el: ‘#app’

el: '#app' 是Vue.js中实例的配置项之一,用于指定Vue实例挂载的元素。
在Vue应用中,我们通常会在HTML页面中指定一个容器元素,用于将Vue实例生成的内容渲染到该容器中。
这个容器元素可以是一个div标签、一个具有唯一ID的元素,或者其他合适的HTML元素。

el: '#app' 就是告诉Vue实例,将其生成的内容挂载到HTML中的ID为app的元素上。
这意味着Vue实例渲染的组件将被动态地插入到HTML页面中具有id="app"的元素中。
在HTML页面中,我们需要确保有一个与el配置项相对应的元素存在。

例如,在HTML中有一个元素


然后我们创建一个Vue实例并将其el配置项设置为'#app',Vue实例生成的内容就会被渲染到
中。
通过使用el配置项,我们可以控制Vue实例的挂载位置,从而将Vue的组件渲染到我们指定的HTML元素中。

1.3 render

在Vue.js中,render是一个配置项,用于定义如何渲染组件。
它是一个函数,接收 createElement 函数作为参数,通过调用 createElement 函数来生成虚拟DOM,并最终渲染成真实的DOM。

通常,render 函数使用箭头函数的简写形式:(h) => h(Component)
其中,hcreateElement 函数的别名,用于创建虚拟DOM。Component 是一个组件的名称或组件选项对象。
例如,render: h => h(App) 指定将 App 组件渲染到根元素上。【个人理解 App 组件应该就是指App.vue

render 配置项的使用方式多种多样,可以根据实际需求,使用函数中的逻辑来动态生成虚拟DOM。
这种方式可以对组件的渲染过程进行更细粒度的控制,比如条件渲染、动态渲染等。
需要注意的是,若配置了 render 函数,则会忽略 templateel 配置项。

2、router.js

2.1 代码

import Vue from 'vue'
import Router from 'vue-router'
/**
 * 安装路由
 * 显示声明使用Router
 * 在main.js里import router from './router',就是指当前目录下router里的index
 */
Vue.use(Router)

/* Layout */
import Layout from '@/layout'

/* Router Modules */
import componentsRouter from './modules/components'
import chartsRouter from './modules/charts'
import tableRouter from './modules/table'
import nestedRouter from './modules/nested'

/**
 * constantRoutes
 * a base page that does not have permission requirements
 * all roles can be accessed
 * 没有权限要求的基页
 * 所有角色都可以访问
 */
// 用于存储常量路由配置
export const constantRoutes = [
  {
    // 路由路径
    path: '/redirect',
    // 跳转的组件 使用名为`Layout`的组件
    component: Layout,
    // 该路径在侧边栏中不可见
    hidden: true,
    // 二级路由 定义了该路径下的子路径,即重定向的某些情况
    children: [
      {
        // 路径为`/redirect`,并以参数的形式传递数据,参数名为`path`;
        path: '/redirect/:path*',
        // 在该路径下使用名为`index`的`redirect`组件
        component: () => import('@/views/redirect/index')
      }
    ]
  },
  {
    path: '/login',
    component: () => import('@/views/login/index'),
    hidden: true
  },
  {
    path: '/auth-redirect',
    component: () => import('@/views/login/auth-redirect'),
    hidden: true
  },
  {
    path: '/404',
    component: () => import('@/views/error-page/404'),
    hidden: true
  },
  {
    path: '/401',
    component: () => import('@/views/error-page/401'),
    hidden: true
  },
  // 定义了一个根路径并重定向到Dashboard页面
  {
    path: '/',
    // 使用名为`Layout`的组件
    component: Layout,
    // 重定向到`/dashboard`路径
    redirect: '/dashboard',
    // 二级路由 定义该路径下的子路径,即`/dashboard`
    children: [
      {
        path: 'dashboard',
        // 在该路径下使用名为`index`的`dashboard`组件
        component: () => import('@/views/dashboard/index'),
        // 该路径的名称为`Dashboard`
        name: 'Dashboard',
        // 路由元信息 title设置该路由在侧边栏和面包屑中展示的名字;  affix如果设置为true,它则会固定在tags-view中(默认 false)
        meta: { title: 'Dashboard', icon: 'dashboard', affix: true }
      }
    ]
  },
  ...
]

/**
 * asyncRoutes
 * the routes that need to be dynamically loaded based on user roles
 * 代表那些需求动态判断权限并通过 addRoutes 动态添加的页面
 */
export const asyncRoutes = [
  {
    path: '/permission',
    component: Layout,
    redirect: '/permission/page',
    alwaysShow: true, // will always show the root menu
    name: 'Permission',
    meta: {
      title: 'Permission',
      icon: 'lock',
      roles: ['admin', 'editor'] // you can set roles in root nav
    },
    children: [
      {
        path: 'page',
        component: () => import('@/views/permission/page'),
        name: 'PagePermission',
        meta: {
          title: 'Page Permission',
          roles: ['admin'] // or you can only set roles in sub nav
        }
      },
      {
        path: 'directive',
        component: () => import('@/views/permission/directive'),
        name: 'DirectivePermission',
        meta: {
          title: 'Directive Permission'
          // if do not set roles, means: this page does not require permission
        }
      },
      {
        path: 'role',
        component: () => import('@/views/permission/role'),
        name: 'RolePermission',
        meta: {
          title: 'Role Permission',
          roles: ['admin']
        }
      }
    ]
  },

  /** when your routing map is too long, you can split it into small modules **/
  componentsRouter,
  chartsRouter,
  nestedRouter,
  tableRouter,
	...
  {
    path: '/error',
    component: Layout,
    redirect: 'noRedirect',
    name: 'ErrorPages',
    meta: {
      title: 'Error Pages',
      icon: '404'
    },
    children: [
      {
        path: '401',
        component: () => import('@/views/error-page/401'),
        name: 'Page401',
        meta: { title: '401', noCache: true }
      },
      {
        path: '404',
        component: () => import('@/views/error-page/404'),
        name: 'Page404',
        meta: { title: '404', noCache: true }
      }
    ]
  },
	...
  // 404 page must be placed at the end !!!
  { path: '*', redirect: '/404', hidden: true }
]

由于代码太长,上面基本就是引入对象组件,定义基本路由和动态路由
下面代码是根据上面内容,创建路由对象

// 定义了一个`createRouter`函数,返回一个新的路由实例;
const createRouter = () => new Router({
  // mode: 'history', // require service support
  // 定义滚动行为,当切换到新路由时,页面滚动到顶部
  scrollBehavior: () => ({ y: 0 }),
  // 使用之前定义的`constantRoutes`常量作为路由配置
  routes: constantRoutes
})

const router = createRouter()

// 导出`resetRouter`,通过调用 `resetRouter` 函数,可以重新创建和设置路由实例,从而达到重置路由的效果
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
export function resetRouter() {
  const newRouter = createRouter()
  // 将新路由实例的 `matcher` 属性赋值给原有的路由实例的 `matcher` 属性,用于重置(重新设置)路由
  router.matcher = newRouter.matcher // reset router
}

// 配置导出路由,这里的router就是上面定义的createRouter方法,返回一个新的路由实例new Router
export default router

2.2 什么是路由Router?

在Vue.js中,路由(Router)是一种管理页面导航的机制,用于实现单页面应用(SPA)中的页面切换和导航功能。
Vue提供了一个名为Vue Router的官方插件,用于实现前端路由功能。
Vue Router允许我们通过定义路由配置,将不同的URL路径映射到对应的组件,然后在应用中进行页面切换和导航。

它使用了类似于URL路径的规则和模式,来决定如何渲染组件,以及如何响应用户的导航操作。
Vue中的路由有以下用途:

  1. 页面切换:通过路由,我们可以根据URL的不同路径,将不同的组件渲染到应用的视图中,从而实现页面的切换效果。比如,点击导航链接或使用前进/后退按钮,就可以在不刷新整个页面的情况下切换到对应的组件。
  2. 嵌套路由:Vue Router支持嵌套路由的定义,可以把一个组件的渲染结果作为另一个组件的子组件,实现页面的层级嵌套结构。
  3. 参数传递:通过路由,我们可以在URL中传递参数,并在组件中通过路由对象进行访问。这样可以实现动态的页面内容展示,比如根据不同的商品ID来展示不同的商品详情页面。
  4. 导航守卫:Vue Router提供了导航守卫的功能,可以在路由的切换过程中,加入一些额外的逻辑处理,比如验证用户权限、拦截未登录用户等。

总结来说,Vue中的路由是用于管理单页面应用中页面切换和导航的机制。它让我们能够根据URL的不同路径,将对应的组件渲染到视图中,并提供了丰富的功能和配置选项,用于处理不同的页面导航需求。

2.3 重置路由的作用?

通常是在某些场景下需要重新配置和匹配路由的情况下使用。以下是重置路由的一些常见用途:

  1. 用户登录/注销:当用户登录或注销时,可能需要根据用户的身份角色重新配置路由。通过重置路由,可以清除旧的路由配置,重新加载、添加和匹配新的路由。
  2. 权限变更:当用户权限发生变化时,可能需要改变可访问的路由页面。重置路由可以清除之前的权限配置,重新加载新的权限配置,并重新匹配路由来控制页面的访问权限。
  3. 动态路由:当需要根据特定条件动态添加或移除路由时,可以先重置路由来清除旧的路由配置,然后再根据特定条件重新添加需要的路由。
  4. 多账号切换:在某些应用中,可能支持多个账号登录并切换。当用户切换账号时,可能需要重新配置路由,清除旧的路由配置,重新加载新的账号的路由配置。

重置路由的目的是为了在特定的场景下,根据新的配置或需求重新设置路由。通过重置路由,可以清除旧的路由配置,以便重新加载新的路由配置,并重新匹配路由,从而实现应用程序的路由动态更新和控制。

2.4 matcher

通过将新路由实例的 matcher 赋值给原有路由实例的 matcher,可以实现路由的重置;
这样做的目的是为了在某些特殊场景下,如用户注销或切换身份角色时,重置路由,清除旧的路由配置,以便重新添加和匹配新的路由

3、store.js

3.1 代码

import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'

// 通过Vue.use()方法,全局注册Vuex插件,使得所有的Vue组件都可以使用Vuex状态管理
Vue.use(Vuex)

/**
 * 使用Webpack的require.context()方法来动态导入当前目录下的所有以.js结尾的文件(模块)
 * context()接收3个参数:directory(目录),useSubdirectories(是否递归子目录),regExp(匹配文件的正则表达式)
 * context函数会返回一个函数,通过调用这个函数并传递文件路径,可以获取到具体的模块。
 * 构建工具需要根据文件目录结构动态地引入和处理模块。例如,在Vue项目中,可以使用require.context来自动注册组件
 */
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', true, /\.js$/)

/**
 * reduce(回调函数,初始值)函数:一个回调函数【(modules, modulePath) =>{...}】和一个初始值【{}】
 * 对下面代码的解释:
 * modules表示累积器,记录每次=>{}里面执行的结果;modulePath表示当前元素
 * 最开始的modules就是reduce()里面参数的{}
 * modulesFiles.keys()是包含匹配模块路径的字符串数组,例如['./app.js','./permission.js',...]
 * modulesFiles是一个函数,返回一个上下文对象
 */
// 通过循环遍历context.keys()得到的所有模块路径(动态导入的模块),
// 使用reduce()方法将它们合并为一个modules对象,最终形成一个字典{'app': './app.js'}
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file
const modules = modulesFiles.keys().reduce((modules, modulePath) => {
  // set './app.js' => 'app'
  const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') // 从模块路径中提取出模块名称
  const value = modulesFiles(modulePath) // 动态导入的模块内容对象,通过`modulePath`作为参数传给`modulesFiles`来获取
  modules[moduleName] = value.default // 将每个模块的名称和内容添加到modules对象中
  return modules
}, {})

// 创建一个Vuex的Store实例,传入modules对象【是state参数】和getters对象作为选项
const store = new Vuex.Store({
  modules,
  getters
})

// 将store对象作为默认导出,以便其他地方可以引用store对象来访问Vuex中的状态、操作以及getters
export default store

3.2 什么是Vuex?

Vuex是Vue的官方状态管理模式和库。在复杂的应用程序中,组件之间共享的状态可能变得混乱和难以管理。
Vuex通过提供一个集中的状态管理机制,让开发人员能够更好地组织、跟踪和管理应用程序的状态。

在Vuex中,应用程序的状态被存储在一个全局的状态树中,可以通过getters来访问,并使用mutations进行修改。
另外,Vuex还提供了actions用于执行异步操作,以及modules用于将状态划分为模块,便于管理和复用。

通过使用Vuex,开发人员可以更好地管理和共享组件之间的状态,并提供一种一致的方式来跟踪和更新应用程序的状态。
这对于大型应用程序和涉及大量数据流的应用程序特别有用。

4、总结✨

看完上面具体内容后,还是容易对整个关系比较混乱,这里总结了一张大致的关系,用来梳理。
【Vue框架】Vue路由配置_第2张图片

你可能感兴趣的:(前端,vue.js,前端,javascript)