vite2+vue3+ant-design 下一代中后台项目的首选
Tips:vue2.0过渡到3.0还算是比较平滑,熟悉基本的响应式语法及Composition API,就可以上手, 又一次巩固了那句vue的slogan 渐进式应用框架!💕, 总的来说vite2会更加亮眼,谁会不喜欢秒启动的 “快感” 呢😜
相关链接:
项目git地址:
- 前端: vite2-vue3-admin
- 后端:eggService
效果图(点击在线预览):
整个框架较多的使用了栅格化内容来适配移动端,
- 左侧菜单部分,数据接口获取,通过vuex集中管理,支持多层菜单,自定义图标
- 左侧菜单在大屏上是固定显示在左侧,在小屏移动端是以抽屉的方式左侧弹出
- 左侧菜单选中,展开状态数据统一由vuex 管理,并使用watchEffect来监听路由变化,来处理获取展示选中,展开菜单数据
整体代码,使用了实验性功能 script setup,部分自定义组件内使用了css 变量 v-bind
1.siderContent
<template>
<div class="siderContent">
<div class="logo">
<img :src="logo" :style="{ width: '48px' }" />
Vite2 Vue3
</div>
<a-menu
:selectedKeys="menuSelectedKeys"
:openKeys="menuOpenKeys"
theme="light"
mode="inline"
:default-selected-keys="[]"
@click="handleCLick"
@select="handleSelect"
@openChange="openChange"
class="g-scrollbar-y"
>
<template v-for="item in menuList">
<a-menu-item v-if="!item.children" :key="item.path">
<icon-font :type="item.iconType" />
<!-- <span>{{ item.title }}</span> -->
<a-badge :dot="!item.show">
{{ item.title }}
</a-badge>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item" />
</template>
</a-menu>
</div>
</template>
<script setup>
import logo from '@/assets/svg/logo.svg'
import subMenu from './subMenu.vue'
import { computed, watchEffect } from 'vue'
import { useStore } from 'vuex'
import { useRouter, useRoute } from 'vue-router'
const Store = useStore()
const Router = useRouter()
const Route = useRoute()
const menuList = computed(() => {
return Store.getters.menuList
})
const initMenuList = () => {
Store.dispatch('menuInfo/generateMenu')
}
initMenuList()
const menuOpenKeys = computed(() => {
return Store.getters.menuOpenKeys
})
const menuSelectedKeys = computed(() => {
return Store.getters.menuSelectedKeys
})
const handleSelect = ({ item, key, selectedKeys }) => {
Store.commit('menuInfo/SET_selectedKeys', selectedKeys)
}
const openChange = keys => {
Store.commit('menuInfo/SET_openKeys', keys)
}
const handleCLick = ({ key }) => {
Store.commit('appInfo/SET_drawerStatus', false)
Router.push({ path: key })
}
watchEffect(() => {
const { matched: matchList } = Route
const validList = matchList.filter(item => {
return !item.meta.hide && item.path !== '/'
})
const [select, ...open] = validList.reverse()
const selectedKeys = [select.path]
const OpenKeys = open.map(item => item.path)
handleSelect({ selectedKeys })
openChange(OpenKeys)
})
</script>
<style scoped lang="less">
.siderContent {
height: 100vh;
padding: 30px 0px;
overflow: auto;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
.logo {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
margin-bottom: 24px;
font-weight: 600;
font-size: 18px;
}
}
.ant-menu-inline {
border: none;
}
</style>
2.sub-menu
<template functional>
<a-sub-menu :key="menuInfo.path">
<template #title>
<icon-font :type="menuInfo.iconType" />
<span>{{ menuInfo.title }}</span>
</template>
<template v-for="item in menuInfo.children">
<a-menu-item v-if="!item.children" :key="item.path">
<icon-font :type="item.iconType" />
<span>{{ item.title }}</span>
</a-menu-item>
<sub-menu v-else :key="item.path" :menu-info="item" />
</template>
</a-sub-menu>
</template>
<script setup>
import { defineProps } from 'vue'
defineProps({
menuInfo: Object,
})
</script>
Tips:vite2中不能使用使用require,所以不能利用require.context进行自动化工程,例如统一装载导出路由模块,vuex模块等
但是vite2中提供了
import.meta.globimport.meta.globEager
替代require.context使用方式
// 导入模块
const modules = import.meta.globEager('./modules/*.js')
const asyncRoutes = []
Object.keys(modules).forEach(file => {
asyncRoutes.push(modules[file].default)
})
export default asyncRoutes
结尾: 希望大家给vite2-vue3-admin 项目点个star😘