前言
随着 vite.js
快速迭代升级,越来越多的开发者倾向于使用vite.js来搭建vue3项目。今天给大家分享 vite4+pinia+ve-plus
开发轻量级后台管理系统项目ViteAdmin。
Vite4-Vue3-Admin 使用前端最新技术vite4+pinia+vue-router@4+
搭建中后台管理模板。
技术框架
- 编码工具:Vscode
- 框架技术:vite4.x+vue3+pinia+vue-router
- UI组件库:vePlus (基于vue3自定义组件库)
- 样式处理:sass^1.58.3
- 图表组件:echarts^5.4.2
- 国际化方案:vue-i18n^9.2.2
- 富文本编辑器组件:wangeditor^4.7.15
- markdown编辑器:md-editor-v3^2.11.0
功能特性
- 支持中文+英文+繁体多语言模式切换。
- 支持表格单选/多选、边框/隔行换色、横向/纵向虚拟滚动条等功能。
- 搭配高颜值vue3组件库VEPlus,风格更加统一。
- 内置多个模板布局样式
- 支持动态路由权限控制
- 支持keepalive路由缓存
- ...
项目结构
vue3组件库ve-plus
ve-plus:一款基于vue3开发的轻量级高定制化UI组件库,包含超过40+常用功能组件。
至于如何安装使用,大家可以去看看之前的这篇分享文章。
https://blog.csdn.net/yanxinyun1990/article/details/129312570
布局模板
vite-admin后台管理提供了4种常用的布局模板。
自定义路由菜单RouteMenu
根据ve-plus组件库提供的Menu组件,结合路由JSON配置,生成路由菜单。
RouteMenu.vue模板
调用方式
vue3国际化多语言vue-i18n
vite-admin支持中英文+繁体切换语言。通过pinia-plugin-persistedstate存储功能。
import { createI18n } from 'vue-i18n'
import { appStore } from '@/store/modules/app'
// 引入语言配置
import enUS from './en-US'
import zhCN from './zh-CN'
import zhTW from './zh-TW'
// 默认语言
export const langVal = 'zh-CN'
export default async (app) => {
const store = appStore()
const lang = store.lang || langVal
const i18n = createI18n({
legacy: false,
locale: lang,
messages: {
'en': enUS,
'zh-CN': zhCN,
'zh-TW': zhTW
}
})
app.use(i18n)
}
lang.vue模板
{{item.label}} {{item.key}}
keepAlive路由缓存
项目支持开启keep-alive动态路由页面缓存功能。
项目中使用pinia2状态管理,pinia-plugin-persistedstate进行本地存储。
/**
* 标签栏缓存状态管理
* 在setup store中
* ref() 就是 state 属性
* computed() 就是 getters
* function() 就是 actions
* @author YXY
* Q:282310962 WX:xy190310
*/
import { ref, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { defineStore } from 'pinia'
import { appStore } from '@/store/modules/app'
export const tabsStore = defineStore('tabs', () => {
const currentRoute = useRoute()
const store = appStore()
/*state*/
const tabViews = ref([]) // 标签栏列表
const cacheViews = ref([]) // 缓存列表
const reload = ref(true) // 刷新标识
// 判断tabViews某个路由是否存在
const tabIndex = (route) => {
return tabViews.value.findIndex(item => item?.path === route?.path)
}
/*actions*/
// 新增标签
const addTabs = (route) => {
const index = tabIndex(route)
if(index > -1) {
tabViews.value.map(item => {
if(item.path == route.path) {
// 当前路由缓存
return Object.assign(item, route)
}
})
}else {
tabViews.value.push(route)
}
// 更新keep-alive缓存
updateCacheViews()
}
// 移除标签
const removeTabs = (route) => {
const index = tabIndex(route)
if(index > -1) {
tabViews.value.splice(index, 1)
}
updateCacheViews()
}
// 移除左侧标签
const removeLeftTabs = (route) => {
const index = tabIndex(route)
if(index > -1) {
tabViews.value = tabViews.value.filter((item, i) => item?.meta?.isAffix || i >= index)
}
updateCacheViews()
}
// 移除右侧标签
const removeRightTabs = (route) => {
const index = tabIndex(route)
if(index > -1) {
tabViews.value = tabViews.value.filter((item, i) => item?.meta?.isAffix || i <= index)
}
updateCacheViews()
}
// 移除其它标签
const removeOtherTabs = (route) => {
tabViews.value = tabViews.value.filter(item => item?.meta?.isAffix || item?.path === route?.path)
updateCacheViews()
}
// 移除所有标签
const clearTabs = () => {
tabViews.value = tabViews.value.filter(item => item?.meta?.isAffix)
updateCacheViews()
}
// 更新keep-alive缓存
const updateCacheViews = () => {
cacheViews.value = tabViews.value.filter(item => store.config.keepAlive || item?.meta?.isKeepAlive).map(item => item.name)
console.log('cacheViews缓存路由>>:', cacheViews.value)
}
// 移除keep-alive缓存
const removeCacheViews = (route) => {
cacheViews.value = cacheViews.value.filter(item => item !== route?.name)
}
// 刷新路由
const reloadTabs = () => {
removeCacheViews(currentRoute)
reload.value = false
nextTick(() => {
updateCacheViews()
reload.value = true
document.documentElement.scrollTo({ left: 0, top: 0 })
})
}
// 清空缓存
const clear = () => {
tabViews.value = []
cacheViews.value = []
}
return {
tabViews,
cacheViews,
reload,
addTabs,
removeTabs,
removeLeftTabs,
removeRightTabs,
removeOtherTabs,
clearTabs,
reloadTabs,
clear
}
},
// 本地持久化存储(默认存储localStorage)
{
// persist: true
persist: {
storage: localStorage,
paths: ['tabViews', 'cacheViews']
}
}
)
-
{{$t(tab.meta?.title)}}
OK,今天就先分享这里,希望大家能喜欢哟~~