使用vite + vue3 + ant-design-vue + vue-router + vuex 创建一个后台管理应用

2023-02-12,,,,

使用vite + vue3 + ant-design-vue + vue-router + vuex 创建一个管理应用的记录

使用vite 创建项目

我创建的node 版本是 v16.17.1

    使用NPM 或者 YARN 安装中选择模板和定义项目名称
npm init vite@latest my-vue-app -- --template vue
yarn create vite my-vue-app -- --template vue
    下载过程中会需要自己选择使用的语言和版本
    下载完项目后,可以启动项目
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
    启动后能看到一个hello vue3 的模板。项目引用的插件基本没有。后面需要用到的自己来安装

安装项目中用到的插件

    这里我简单安装了如下插件
"ant-design-vue": "^3.2.13",
"axios": "^1.1.3",
"c-scrollbar": "^1.0.2",
"vue": "^3.2.41",
"vue-router": "4",
"vuex": "^4.1.0" "less": "^4.1.3",
"unplugin-vue-components": "^0.22.9",

项目使用了 ant-design-vue 先来说下UI 组件的配置

[文档] https://www.antdv.com/docs/vue/getting-started-cn

这里我介绍下 我使用的按需加载的配置。 在vite.congig.js 中

import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
import Components from 'unplugin-vue-components/vite'
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [
AntDesignVueResolver()
]
})
],
})

设置完,在组件中就可以直接使用框架提供的UI 组件, 写法上比较方便了。

项目请求服务端的跨域配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { AntDesignVueResolver } from 'unplugin-vue-components/resolvers'
import Components from 'unplugin-vue-components/vite'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [
AntDesignVueResolver()
]
})
],
server: {
proxy: {
"/api": {
target: "要请求的地址",
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
})

配置axios 统一请求拦截器添加的参数,和配置响应的分类

一般在发送服务请求的时候,会在请求头中添加验证的token ,配置请求地址中识别需要跨域处理的关键字端。

响应中根据返回的结果,按统一的结构返回到请求的API中

import axios from 'axios'
import store from '@/store'
import router from '@/route/index.js'
axios.defaults.timeout = 30000
// 返回其他状态吗
axios.defaults.validateStatus = function (status) {
return status >= 200 && status <= 500 // 默认的
}
// 跨域请求,允许保存cookie
axios.defaults.withCredentials = true axios.interceptors.request.use(config => {
config.url = '/api' + config.url
const token = store.state.token
const TENANT_ID = 1
if (token) {
config.headers['Authorization'] = 'Bearer ' + token// token
}
if (TENANT_ID) {
config.headers['TENANT-ID'] = TENANT_ID // 租户ID
}
return config
}, error => {
return Promise.reject(error)
}) axios.interceptors.response.use(res => {
const httpStatus = res.status
if (httpStatus === 200) {
const code = res.data.code
if (code === 0) {
return res.data.data
}else{
return Promise.reject(new Error(res.data.msg))
}
}else{
router.push({
path: '/login'
})
return Promise.reject(new Error(res.statusText))
} }, error => {
// 处理 503 网络异常
if (error.response.status === 503) { }
return Promise.reject(new Error(error))
}) export default axios

vuex 在项目中的配置,使用

[文档地址]https://vuex.vuejs.org/zh/guide/

上面的请求拦截器中我们使用到了token, token保存在了vuex 的store 中。

下面介绍下 vuex 的配置和使用

    首先下载vuex ,在开始的时候 已经将用到的依赖插件下载好了,版本是 4.1.0
    创建store.js 包含state, mutatins, actions, getter
import {createStore} from 'vuex'
const state = {
allRoutes: [],
token: '',
};
const mutations = {
set_allRoutes(state,payload){
state.allRoutes = payload
},
set_token(state, token) {
state.token = token
}
}
const actions = {
set_access_token(context, token) {
return new Promise(resolve => {
context.commit('set_token', token)
resolve()
})
}
}
const getter = {
allRoutes(state) {
return state.allRoutes
}
}
const options = {
state,
mutations,
actions,
getter
}
const store = createStore(options)
export default store
    在main.js中
import { createApp } from 'vue'
import App from './App.vue'
import store from '@/store/index'
const app = createApp(App)
app.use(router).use(store).mount('#app')
    使用中可以使用 commit, dispatch 来调用mutations, commit 中修改数据的方法

    4.1 使用dispatch 异步修改数据

import { defineComponent, reactive } from 'vue';
import { useStore } from 'vuex'
import {useRouter} from 'vue-router'
export default defineComponent({
setup() {
const store = useStore()
const route = useRouter()
const onFinish = values => {
let token = '12b02935-e967-4ef6-9276-6207f4fff6e8'
store.dispatch('set_access_token', token).then(() => {
route.push({
path: '/'
})
})
};
return {
onFinish,
};
}, });

4.2 使用commit 同步修改数据

const store = useStore()
store.commit('set_allRoutes', res);
    组件中使用存储的数据
import {useStore} from 'vuex'
const store = useStore()
let menu = store.state.allRoutes

vue-router 的基本使用,和动态路由的添加

在应用中 vue-router 帮助开发者实现了前端路由,[参考文档]https://router.vuejs.org/zh/

    基本的路由配置也比较简单,参考如下
route/index.js
import {createRouter,createWebHashHistory} from 'vue-router'
import Home from '../page/Home.vue'
import Login from '@/page/login/index.vue'
const routes = [
{
path: '/',
redirect: '/index/hello'
},
{
path: '/login',
name: 'login',
component:Login
},
{
path: '/index',
component: Home,
children: [
{ path: 'hello',name: 'hello', component: () => import ('../components/HelloWorld.vue') }, ],
}
]
const router = createRouter({
// 4. 内部提供了 history 模式的实现。为了简单起见,我们在这里使用 hash 模式。
history: createWebHashHistory(),
routes, // `routes: routes` 的缩写
})
export default router

根据上面的写法很容易实现路由和子路由的添加

2. 项目中,一般会有根据用户请求,返回自己拥有的路由权限来动态添加路由

在这里 我做了个简单的示例,

这里选用动态添加路由的方式为 router.addRoute

import router from './index'
import Home from '../page/Home.vue'
import {fetchMenuList} from '@/api/main.js'
const modules = import.meta.glob("../**/**/**.vue")
function addRoute (list) {
list.forEach(item => {
if (item.path === '/admin') {
let routelist = []
item.children.forEach(child => {
let path = child.path.slice(0)
let r = {path: path, name: child.name, component: modules[`../view${child.path}.vue`]}
routelist.push(r)
}) router.addRoute(
{
path: item.path,
component: Home,
children: routelist
}
)
}
}) }

上面代码中 fetchMenuList 是获取用户路由权限的接口,

Home 是要添加的二级路由的 父组件, 接口中获取的数据比较多, 这里只添加了 amdin 一级路由下的二级路由, 如果有多个,也是这个思路

在这需要注意的是 子路由的引用方式,观察代码和 最初简单的添加方式,路由地址引用的模式发生了变化, 这个是因为使用 vite 来编译代码,需要做的处理。 这里不做具体介绍。

下面是权限代码中 添加动态路由的代码

import router from './index'
import Home from '../page/Home.vue'
import store from '@/store'
import {fetchMenuList} from '@/api/main.js'
const modules = import.meta.glob("../**/**/**.vue")
function addRoute (list) {
list.forEach(item => {
if (item.path === '/admin') {
let routelist = []
item.children.forEach(child => {
let path = child.path.slice(0)
let r = {path: path, name: child.name, component: modules[`../view${child.path}.vue`]}
routelist.push(r)
}) router.addRoute(
{
path: item.path,
component: Home,
children: routelist
}
)
}
}) }
const getRouteInfo = () => {
const allRoutes = store.state.allRoutes
return new Promise(resolve => {
if (allRoutes.length === 0) { fetchMenuList().then(res => {
addRoute(res)
store.commit('set_allRoutes', res);
resolve()
})
}else {
addRoute(allRoutes)
resolve()
}
})
}
let menuRouter = false
router.beforeEach((to, from , next) => {
if (store.state.token) {
if (!menuRouter) { getRouteInfo().then(() => {
menuRouter = true
next({...to, replace: true});
})
}else{
next()
}
}else {
if (to.path == '/login') {
next()
}else{ next('/login')
}
}
})

后面的文章,会接着介绍 项目其他相关内容, 欢迎点赞加关注

这里介绍下本人做的头像,壁纸小程序,欢迎大家体验,

热门头像|个性头像|高清头像|性感壁纸|美女壁纸|炫酷壁纸|省电壁纸|唯美壁纸

使用vite + vue3 + ant-design-vue + vue-router + vuex 创建一个后台管理应用的相关教程结束。

《使用vite + vue3 + ant-design-vue + vue-router + vuex 创建一个后台管理应用.doc》

下载本文的Word格式文档,以方便收藏与打印。