2. vue3+ts+element-plus 배경 관리 인터페이스 레이아웃 및 동적 사이드바 구현

1. 인터페이스 레이아웃

  요소와 레이아웃 구성 요소를 사용하여 <el-container> 전체 레이아웃 컨테이너, <el-header> 상단 레이아웃 컨테이너, <el-aside> 측면 레이아웃 컨테이너 <el-main> 기본 레이아웃 컨테이너를 구현합니다. 구성 요소화 아이디어를 사용하여 헤더와 옆 부분을 구성 요소화하여 레이아웃을 용이하게 합니다.

<template>
  <div class="common-layout">
    <el-container>

      <CommonAside />

      <el-container>
        <el-header>
          <CommonHeader />
        </el-header>
        <el-main>
          <router-view />
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>
<script lang="ts" setup>
import CommonAside from '../components/CommonAside.vue'
import CommonHeader from '../components/CommonHeader.vue'

</script>
  color: var(--el-text-color-primary);
}</style>

2. 사이드바 레이아웃 및 동적 구현 기술

사이드바의 레이아웃은 element-plus의 el-menu 구성 요소를 사용하여 구현됩니다. el-menu 구성 요소는 첫 번째 수준 메뉴를 구현하고 el-submenu는 두 번째 수준 메뉴를 구현합니다. el-menu-item은 메뉴 항목을 구현하고 el-submenu-item은 보조 메뉴 항목을 구현합니다. el-menu-item-group은 메뉴 그룹을 구현하고 el-menu-item-group은 메뉴 그룹을 구현합니다.

      모든 메뉴 내용은 menuData 배열에 저장되며 v-for 명령을 통해 동적으로 렌더링됩니다. noChildren을 사용하면 첫 번째 수준 메뉴 데이터인 하위 메뉴가 없는 메뉴 데이터를 필터링할 수 있습니다. 보조 메뉴 데이터인 hasChildren을 통해 하위 메뉴가 포함된 메뉴 데이터를 필터링합니다.

  설명해야 할 내용은 vue3 및 element-plus에 있습니다. 
 1. el-menu-item 및 el-submenu-item 구성 요소의 이름 속성 값은 고유해야 하며, 그렇지 않으면 오류가 보고됩니다. 
  index 속성도 고유해야 합니다. 그렇지 않으면 실제 메뉴에서 항목을 클릭할 때 모든 항목이 응답합니다.
 2. 아이콘은 컴포넌트 디자인을 채택하고 있으며 이전 버전과 달리 문자열을 이어붙여 컴포넌트를 호출합니다(대부분의 이전 구현에서는 이 방법을 사용했습니다). 구체적으로:

   <컴포넌트 :is="item.icon" ></컴포넌트>

   이 구현 참조 문서: https://blog.csdn.net/qq_40190624/article/details/125019530이 더 자세히 설명되어 있습니다.

추천 ai: <el-icon><icon-svg :icon-class="item.icon" /></el-icon>

   아이콘을 커스터마이징해야 하는 경우, 아이콘폰트 공식 홈페이지에서 다운로드하여 static 폴더에 넣은 후 import를 통해 도입하시면 됩니다. https://blog.csdn.net/qq_39246667/article/details/124347398 구체적인 방법은 더 복잡합니다.

  3. noChildren() 메소드는 v-for에서 함수를 직접 호출하는 대신 코드에서 쉽게 호출할 수 있도록 특정 변수로 저장하는 것이 가장 좋습니다.
<template>
    <!-- <el-radio-group v-model="isCollapse" style="margin-bottom: 20px">
      <el-radio-button :label="false">expand</el-radio-button>
      <el-radio-button :label="true">collapse</el-radio-button>
    </el-radio-group> -->
    <el-menu default-active="2" class="el-menu-vertical-demo" :collapse="isCollapse" @open="handleOpen"
        @close="handleClose">
        <el-menu-item v-for="item in noChildren()" :key="item.name" :index="item.name">
            <component :is="item.icon" style="width: 18px;height: 18px;"></component>
            <template #title>{
   
   {item.label}}</template>
        </el-menu-item>
        <el-sub-menu v-for="item in hasChildren()" :key="item.name" :index="item.label">
            <template #title>
                <el-icon>
                    <component :is="item.icon" style="width: 18px;height: 18px;"></component>
                </el-icon>
                <span>{
   
   {item.label}}</span>
            </template>
            <el-menu-item-group v-for="subItem in item.children" :key="subItem.name">
            <el-menu-item :index="subItem.name">{
   
   {subItem.label}}</el-menu-item>
           </el-menu-item-group>
        </el-sub-menu>
    </el-menu>
</template>
  
<script lang="ts" setup>
import { ref } from 'vue'
import {
    Document,
    Menu as IconMenu,
    Location,
    Setting,
} from '@element-plus/icons-vue'

// 声明一个变量isCollapse,值为false
const isCollapse = ref(false)

const menuData = [
    {
        path: "/",
        name: "home",
        label: "首页",
        icon: 'Menu',
        url: "Home/Home",
    },
    {
        path: "/mall",
        name: "mall",
        label: "商品管理",
        icon: "Document",
        url: "MallManage/MallManage",
    },
    {
        path: "/user",
        name: "user",
        label: "用户管理",
        icon: "Setting",
        url: "UserManage/UserManage",
    },
    {
        label: "其他",
        icon: "location",
        children: [
            {
                path: "/page1",
                name: "page1",
                label: "首页",
                icon: "Setting",
                url: "Other/PageOne",
            },
            {
                path: "/page2",
                name: "page2",
                label: "首页",
                icon: "Setting",
                url: "Other/PageTwo",
            },
        ],
    },
]
// 声明一个函数handleOpen,参数为key和keyPath,用于接收参数
const handleOpen = (key: string, keyPath: string[]) => {
    console.log(key, keyPath)
}
// 声明一个函数handleClose,参数为key和keyPath,用于接收参数
const handleClose = (key: string, keyPath: string[]) => {
    console.log(key, keyPath)
}
const noChildren = () => { return menuData.filter((item) => !item.children) }
// 过滤出没有子菜单的菜单数据

const hasChildren = () => { return menuData.filter((item) => item.children) }
// 过滤出有子菜单的菜单数据

</script>
  
<style>
.el-menu-vertical-demo:not(.el-menu--collapse) {
    width: 200px;
    min-height: 400px;
}
</style>
  

참고: 색인 항목은 고유해야 합니다: index="item.label" item.label 옵션은 각 메뉴에서 사용할 수 있으며 서로 다릅니다. 하위 메뉴 항목 제목에는 이름이 없으므로 item.name은 오류를 보고합니다.

추천

출처blog.csdn.net/lap2004/article/details/132333254