为了看后端权限在前端的使用,阅读vue-element-admin-4.2.1代码来进行理解;同时了解一下前端框架,并对部分内容进行详细介绍(学习)。本文主要从main.js来看各个内容,并整理main,router和store间的关系。
代码下载:vue-element-admin-4.2.1
PS:本文虽然很长,但是其实很简单,代码上已经写好注释,慢慢看
这里主要介绍一些主要内容,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`组件
})
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元素中。
在Vue.js中,
render
是一个配置项,用于定义如何渲染组件。
它是一个函数,接收createElement
函数作为参数,通过调用createElement
函数来生成虚拟DOM,并最终渲染成真实的DOM。
通常,
render
函数使用箭头函数的简写形式:(h) => h(Component)
。
其中,h
是createElement
函数的别名,用于创建虚拟DOM。Component
是一个组件的名称或组件选项对象。
例如,render: h => h(App)
指定将App
组件渲染到根元素上。【个人理解App
组件应该就是指App.vue
】
render
配置项的使用方式多种多样,可以根据实际需求,使用函数中的逻辑来动态生成虚拟DOM。
这种方式可以对组件的渲染过程进行更细粒度的控制,比如条件渲染、动态渲染等。
需要注意的是,若配置了render
函数,则会忽略template
和el
配置项。
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
在Vue.js中,路由(Router)是一种管理页面导航的机制,用于实现单页面应用(SPA)中的页面切换和导航功能。
Vue提供了一个名为Vue Router的官方插件,用于实现前端路由功能。
Vue Router允许我们通过定义路由配置,将不同的URL路径映射到对应的组件,然后在应用中进行页面切换和导航。
它使用了类似于URL路径的规则和模式,来决定如何渲染组件,以及如何响应用户的导航操作。
Vue中的路由有以下用途:
- 页面切换:通过路由,我们可以根据URL的不同路径,将不同的组件渲染到应用的视图中,从而实现页面的切换效果。比如,点击导航链接或使用前进/后退按钮,就可以在不刷新整个页面的情况下切换到对应的组件。
- 嵌套路由:Vue Router支持嵌套路由的定义,可以把一个组件的渲染结果作为另一个组件的子组件,实现页面的层级嵌套结构。
- 参数传递:通过路由,我们可以在URL中传递参数,并在组件中通过路由对象进行访问。这样可以实现动态的页面内容展示,比如根据不同的商品ID来展示不同的商品详情页面。
- 导航守卫:Vue Router提供了导航守卫的功能,可以在路由的切换过程中,加入一些额外的逻辑处理,比如验证用户权限、拦截未登录用户等。
总结来说,Vue中的路由是用于管理单页面应用中页面切换和导航的机制。它让我们能够根据URL的不同路径,将对应的组件渲染到视图中,并提供了丰富的功能和配置选项,用于处理不同的页面导航需求。
通常是在某些场景下需要重新配置和匹配路由的情况下使用。以下是重置路由的一些常见用途:
- 用户登录/注销:当用户登录或注销时,可能需要根据用户的身份角色重新配置路由。通过重置路由,可以清除旧的路由配置,重新加载、添加和匹配新的路由。
- 权限变更:当用户权限发生变化时,可能需要改变可访问的路由页面。重置路由可以清除之前的权限配置,重新加载新的权限配置,并重新匹配路由来控制页面的访问权限。
- 动态路由:当需要根据特定条件动态添加或移除路由时,可以先重置路由来清除旧的路由配置,然后再根据特定条件重新添加需要的路由。
- 多账号切换:在某些应用中,可能支持多个账号登录并切换。当用户切换账号时,可能需要重新配置路由,清除旧的路由配置,重新加载新的账号的路由配置。
重置路由的目的是为了在特定的场景下,根据新的配置或需求重新设置路由。通过重置路由,可以清除旧的路由配置,以便重新加载新的路由配置,并重新匹配路由,从而实现应用程序的路由动态更新和控制。
通过将新路由实例的
matcher
赋值给原有路由实例的matcher
,可以实现路由的重置;
这样做的目的是为了在某些特殊场景下,如用户注销或切换身份角色时,重置路由,清除旧的路由配置,以便重新添加和匹配新的路由
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
Vuex是Vue的官方状态管理模式和库。在复杂的应用程序中,组件之间共享的状态可能变得混乱和难以管理。
Vuex通过提供一个集中的状态管理机制,让开发人员能够更好地组织、跟踪和管理应用程序的状态。
在Vuex中,应用程序的状态被存储在一个全局的状态树中,可以通过
getters
来访问,并使用mutations
进行修改。
另外,Vuex还提供了actions
用于执行异步操作,以及modules
用于将状态划分为模块,便于管理和复用。
通过使用Vuex,开发人员可以更好地管理和共享组件之间的状态,并提供一种一致的方式来跟踪和更新应用程序的状态。
这对于大型应用程序和涉及大量数据流的应用程序特别有用。