学习搭建后台管理系统模板之vuex和vuerouter

本项目学习对象是优秀的后台系统模板vben-admin,期待通过学习解读该项目,熟悉前端项目工程化。

内容

  1. VUEX 状态管理工具
  2. Vue Router 路由管理
1. VUEX 状态管理工具
1.1 安装
npm install vuex@next --save
1.2 自动导入modules文件夹中写的module

src/store/index.ts

import type { App } from 'vue'
import { createStore } from 'vuex'

// 导出module目录中的内容
const modules: any = {}
const modulesFiles = import.meta.globEager('./module/*.ts')
Object.keys(modulesFiles).forEach((path) => {
    const moduleName = path.split('/')[2].split('.')[0]
    modules[moduleName] = modulesFiles[path].default
    modules[moduleName].namespaced = true // 防止模块命名冲突 设置后调用mutations和action需要
})
// 创建vuex实例
const store = createStore({
  modules
})
/**
 * @description: 用于在main.js中注册vuex实例
 * @param {App} app
 * @return {*}
 */
export function setupStore(app: App<Element>) {
  app.use(store)
}
/**
 * @description: 抛出vuex实例,方便使用
 * @param {*}
 * @return {*}
 */
export function useStore() {
  return store
}

1.3 例子

src/store/module/user.ts

import type { UserInfo } from '#/store.d'

export interface UserState {
  userInfo: UserInfo | null
}

export default {
  state: (): UserState => ({
    userInfo: null
  }),
  mutations: {
    SET_USER_INFO(state: UserState, info: UserInfo) {
      state.userInfo = info
    }
  },
  getters: {
    getUserInfo(state: UserState) {
      return state.userInfo
    }
  }
}

src/types/store.d.ts —用到的类型声明

export interface UserInfo {
  userId: string | number
  username: string
  realName: string
}
1.4 使用
1.4.1 在main.ts入口文件中挂载
import { createApp } from 'vue'
import { setupStore } from '@/store'
import App from './App.vue'

const app = createApp(App)

// 挂载vuex
setupStore(app)

app.mount('#app')

src/App.vue

1.4.2 在App.vue中调用看看
<template>
  {{ userinfo }}
</template>

<script lang="ts" setup>
import { useStore } from '@/store'

const Store = useStore()
const userinfo = Store.getters['user/getUserInfo']
console.log(userinfo)
</script>

控制台正确输入了null
在这里插入图片描述

2. Vue Router 路由管理
2.1安装
npm install vue-router@4 -S
2.2 router配置

src/router/index.ts —router的入口

import type { App } from 'vue'
import type { RouteRecordRaw } from 'vue-router'
import { createRouter, createWebHashHistory } from 'vue-router'
import { WHITE_NAME_LIST } from './constant'
import { basicRoutes } from './routes'
// 路由
export const router = createRouter({
  // 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
  history: createWebHashHistory(), // 使用无需对服务器进行设置的hash路由方式
  routes: [...basicRoutes] as RouteRecordRaw[] // 传入路由列表
})

// 初始化挂载路由
export function setupRouter(app: App<Element>) {
  app.use(router)
}

// 重置路由
export function resetRouter() {
  router.getRoutes().forEach((route) => {
    const { name } = route
    // 如果路由存在且不在白名单中则删除
    if (name && !WHITE_NAME_LIST.includes(name as string)) {
      router.hasRoute(name) && router.removeRoute(name)
    }
  })
}

src/router/constant.ts —常量配置

export const REDIRECT_NAME = 'Redirect'
// 白名单
export const WHITE_NAME_LIST = [REDIRECT_NAME, 'Login']
export const LAYOUT = () => import('@/layout/index.vue')
export const EMPTY_LAYOUT = () => import('@/layout/Empty.vue')
export const EXCEPTION_COMPONENT = () => import('@/views/sys/exception/index.vue')

src/router/routes/index.ts — 路由列表的获取

import type { RouteRecordRaw } from 'vue-router'
import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from './basic'

const modules = import.meta.globEager('./modules/**/*.ts')
const routeModuleList: RouteRecordRaw[] = []

Object.keys(modules).forEach((key) => {
  const mod = modules[key].default || {}
  const modList = Array.isArray(mod) ? [...mod] : [mod]
  routeModuleList.push(...modList)
})

export const RootRoute = {
  path: '/',
  name: 'Root',
  redirect: '/dashboard',
  meta: {
    title: 'Root'
  }
}

export const LoginRoute = {
  path: '/login',
  name: 'Login',
  component: () => import('@/views/sys/login/index.vue'),
  meta: {
    title: '登录页'
  }
}

export const basicRoutes = [LoginRoute, RootRoute, REDIRECT_ROUTE]
// 现在默认的异步路由(即接口获取的)是全部的路由
export const asyncRoutes = [PAGE_NOT_FOUND_ROUTE, ...routeModuleList]

src/router/routes/basic.ts —最基础的路由

import type { AppRouteRecordRaw } from '@/router/types'
import { REDIRECT_NAME, LAYOUT, EXCEPTION_COMPONENT } from '@/router/constant'

export const PAGE_NOT_FOUND_ROUTE: AppRouteRecordRaw = {
  path: '/:path(.*)*',
  name: 'ErrorPage',
  component: LAYOUT,
  meta: {
    title: 'ErrorPage',
    hideBreadcrumb: true
  },
  children: [
    {
      path: '/:path(.*)*',
      name: 'ErrorPage',
      component: EXCEPTION_COMPONENT,
      meta: {
        title: 'ErrorPage',
        hideBreadcrumb: true
      }
    }
  ]
}

export const REDIRECT_ROUTE: AppRouteRecordRaw = {
  path: '/redirect',
  name: REDIRECT_NAME,
  component: LAYOUT,
  meta: {
    title: REDIRECT_NAME,
    hideBreadcrumb: true
  },
  children: [
    {
      path: '/redirect/:path(.*)',
      name: REDIRECT_NAME,
      component: () => import('@/views/sys/redirect/index.vue'),
      meta: {
        title: REDIRECT_NAME,
        hideBreadcrumb: true
      }
    }
  ]
}

src/router/types.ts —路由相关的类型声明

import type { RouteRecordRaw } from 'vue-router'
import { defineComponent } from 'vue'
export type Component<T = any> = ReturnType<typeof defineComponent> | (() => Promise<typeof import('*.vue')>) | (() => Promise<T>)

export interface RouteMeta {
  // title
  title: string
  type?: string
  icon?: string
}
export interface AppRouteRecordRaw extends Omit<RouteRecordRaw, 'meta'> {
  name: string
  meta: RouteMeta
  component?: Component | string
  components?: Component
  children?: RouteRecordRaw[]
  props?: any
  fullPath?: string

src/App.vue

<template>
  <div><router-view /></div>
</template>

<script lang="ts" setup></script>

src/views/sys/login/index.vue

<template>
  <div>登录</div>
</template>
<script lang="ts">
export default { name: 'LoginPage' }
</script>

1.3 使用

src/main.ts

在这里插入图片描述

访问login页面

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值