一、为什么我要用tsx封装左侧栏菜单
在我们日常开发中 有时候会经常遇到如下图这种多层级的菜单栏,如果单单只用原本的vue开发起来会比较麻烦,而如果使用tsx则可以在一个.vue文件中实现 任意层级的菜单栏 ,这就是tsx的灵活性
二、使用步骤
在使用tsx之前 我们要安装一些插件 使我们的项目支持tsx
1.安装
//下面3种安装方式选择一种 推荐pnpm
yarn add @vitejs/plugin-vue-jsx
//or
npm install @vitejs/plugin-vue-jsx -D
//or
pnpm install @vitejs/plugin-vue-jsx -D
2.配置
在
vite.config.ts
文件中挂载
import vueJsx from '@vitejs/plugin-vue-jsx'
export default defineConfig({
plugins: [ vueJsx()]
})
tsconfig.json
文件中
{
// include 需要包含tsx
"include": ["src/*", "src/**/*.vue", "src/**/*.tsx", "src/**/*.jsx", "src/**/*.ts", "src/**/*.js"],
"compilerOptions": {
// 在.tsx文件里支持JSX
"jsx": "preserve",
}
}
三、tsx 任意层级菜单栏实现代码
新建AppAside.vue 文件 放入如下代码:
<script lang="tsx" name="AppAside">
const AppAside = defineComponent({
props: {
//菜单数据获取
menuList: {
type: Array,
default: () => {
return []
},
},
},
setup(props) {
const route = useRoute()
const router = useRouter()
const activeIndex = computed(() => route.path.split('/').slice(-1)[0])
//菜单生成
const getMenu = (menuList: any) => {
return menuList.map((item: any) => {
if (item.children && item.children.length > 0 && !item.hidden) {
const slots = {
title: () => (
<span class="flex flex-center">
{item.meta.icon ? (
<svg-icon name={item.meta.icon} size="20px"></svg-icon>
) : (
''
)}
<span class="title">{item.meta.title}</span>
</span>
),
}
return (
<el-sub-menu index={item.path} v-slots={slots}>
{getMenu(item.children)}
</el-sub-menu>
)
} else if (!item.hidden) {
return (
<el-menu-item index={item.path}>
{item.meta.icon ? (
<svg-icon name={item.meta.icon} size="20px"></svg-icon>
) : (
''
)}
<span class="title">{item.meta.title}</span>
</el-menu-item>
)
}
})
}
//路由跳转
const handleSelect = (key: string, keyPath: string[]) => {
const path = `/${keyPath.join('/')}`
router.push({
path,
})
}
return () => (
<el-menu
default-active={activeIndex}
active-text-color="#ffd04b"
background-color="#545c64"
class="el-menu-vertical-demo"
text-color="#fff"
onSelect={handleSelect}
>
{activeIndex}
{getMenu(props.menuList)}
</el-menu>
)
},
})
export default AppAside
</script>
<style lang="scss" scoped>
.el-menu {
height: calc(100vh - 50px);
}
.el-menu-item.is-active {
background: linear-gradient(-90deg, #29bdd9 0%, #276ace 100%) !important;
color: #fff;
span {
color: #fff !important;
}
}
.title {
margin-left: 10px;
}
</style>