본문 바로가기
Programming/Vue

[실습] 뷰(Vue.js)로 관리자/직원 전용 Web Application 개발하기 - 메뉴(Side Bar, Navigation Bar) 구성/구현하기

by 돌방로그 2023. 1. 2.

제목의 글을 설명하기에 앞서 정보전달의 목적도 있지만, 

제가 잊지않기 위해서 공부 및 정리하며 쓰는 글이라는 사실을 미리 고지합니다.

 

혹시라도 오입력된 정보가 있다면, 댓글 남겨주세요!


오늘의 Vue.js 실습 목표는 "웹 어플리케이션 (Web Application) 만들어보기!" 입니다.

본 게시글에서 다루는 사항은 관리자/직원 전용 웹 어플리케이션의 메뉴, 네비게이션/사이드 바 영역을 구현하는 과정입니다.

 


웹 어플리케이션(Web Application) 구현하기 - 메뉴(SideBar, Navigation Bar)

사전 준비

아래 사항에 대해서 사전 준비가 완료되지 않으신 분들은 아래 링크를 참조하여 사전 준비를 진행합니다.

혹시라도 아래 개념이 잘 기억나지 않으시는 분들은 관련 링크를 참조하시기 바랍니다.

 

 

파일 구조

관리자/직원 전용 Web Application의 메뉴를 구현하고 난 뒤, 파일/디렉터리 구조와 호출 흐름도입니다.

Web Application 메뉴를 구성/구현하기 위해 작업할 파일은 총 1개, "App.vue 파일입니다.

 

> 파일/폴더 트리

 

> 호출 흐름도

 

 

Layout

Navigation/Side Bar 영역은 크게 2가지 영역으로 구성되어 있습니다.

  • User Information: 로그인한 사용자의 정보가 표시 및 관리하는 영역 
  • Menu: 관리자 포털에서 제공되는 메뉴가 표시되는 영역으로 크게 3가지 세부 영역으로 구성됨
    • 로그인한 모든 사용자에게 보여지는 메뉴
    • 특정 권한에 따라 보여지는 메뉴
      • 이용자 포털 관련하여 권한이 있는 사용자에게 보여지는 메뉴
      • 관리자 포털 관련하여 권한이 있는 사용자에게 보여지는 메뉴

 

 

결과 이미지

구현하기에 앞서 본 글에서 기획/설계한 사항을 따라하시면 아래와 같이 웹 어플리케이션의 메뉴(사이드바, 네비게이션 바)를 구현하실 수 있습니다.

 

 

 

소스 코드

본 게시글에서는 Navigation/Side Bar 영역에 메뉴 리스트와 사용자 정보를 표시하는 기능을 구현합니다.

권한 별 메뉴를 Show/Hide하는 기능이나 각 메뉴 별 페이지는 별도의 게시글로 소개할 예정입니다.

 

src\App.vue

Web Application의 Layout을 구성하는 파일로 Vuetify를 이용하여 구현합니다.

Navigation/Side Bar는 Vuetify의 Lists의 NavSub Group을 이용하여 구현하였습니다.

 

1. Menu List

<template>

<template>
  <v-app>
    <v-navigation-drawer app>
      <v-list dense>
        ...

        <!-- Menu/Navigation Bar list -->
        <v-list-item-group v-model="selectedItem" color="primary">
          <v-list-item v-for="(item, i) in navBasicItems" :key="i">
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>

          <v-divider></v-divider>

          <v-subheader>User Web</v-subheader>
          <v-list-item v-for="(item, i) in navUserWebItems" :key="i">
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
          
          <v-divider></v-divider>
          
          <v-subheader>Admin Web</v-subheader>
          <v-list-item v-for="(item, i) in navAdminWebItems" :key="i">
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-navigation-drawer>
    ...
  </v-app>
</template>
  • <v-divider>: 영역의 구분선을 표시하는 태그
  • <v-subheader>: 영역의 타이틀을 표시하는 태그
  • <v-list-item-group>: 리스트 아이템의 그룹으로 'v-model'을 통해 현재 선택된 리스트 아이템을 관리
  • <v-list-item>: 리스트 아이템으로 'v-for'를 통해 <script>의 data 영역에 지정된 요소를 화면에 표시하는 태그
    • <v-list-item-icon>: 리스트 아이템의 아이콘 설정 태그
      • <v-icon>: 아이콘 태그
    • <v-list-content>: 리스트 아이템의 콘텐츠 설정 태그
      • <v-list-item-title>: 리스트 아이템의 텍스트/타이틀 설정 태그

 

<script>

<script>
export default {
  name: 'App',

  data: () => ({
    // For Menu/Navigation Bar
    navSelectedItem: 0,
    navBasicItems: [
      { text: 'Dashboard', icon: 'mdi-view-dashboard' },
      { text: 'Setting', icon: 'mdi-cog-outline' }
    ],
    navUserWebItems: [
      { text: 'Notice', icon: 'mdi-file-outline' },
      { text: 'User Management', icon: 'mdi-account' },
      { text: 'Menu Management', icon: 'mdi-lan-check' },
    ],
    navAdminWebItems: [
      { text: 'User Management', icon: 'mdi-account-supervisor-circle' },
      { text: 'Rights Management', icon: 'mdi-lock-open' },
    ]
  }),
};
</script>
  • data 영역
    • navSelectedItem: 메뉴 리스트에서 선택된 리스트 항목을 관리
    • 메뉴 리스트 (→ 향후 <script> 영역의 데이터가 아닌 DB에서 관리하는 데이터로 변경 예정)
      • 구성: 메뉴 타이틀(text), 이미지(icon)
        • 경로(to)는 콘텐츠 영역을 구현하면서 구현 완료된 사항에 대해서만 추가할 예정
      • 메뉴 종류: 권한에 따라 사용되는 메뉴 리스트가 다름 
        • navBasicItems: 메뉴 리스트 중에서 로그인한 모든 사용자
        • navUserWebItems: 메뉴 리스트 중에서 이용자 포털관련 권한이 있는 사용자
        • navAdminWebItems: 메뉴 리스트 중에서 관리자 포털관련 권한이 있는 사용자

 

2. User Information

<template>

<template>
  <v-app>
    <v-navigation-drawer app>
      <v-list dense>
        <!-- User(Employee) information -->
        <v-list-item>
          <v-list-item-avatar>
            <v-img src="https://cdn.vuetifyjs.com/images/john.png"></v-img>
          </v-list-item-avatar>
        </v-list-item>
        <v-list-item link>
          <v-list-item-content>
            <v-list-item-title class="text-h6">Sylvia Park</v-list-item-title>
            <v-list-item-subtitle>ardiums@gmail.com</v-list-item-subtitle>
          </v-list-item-content>
        </v-list-item>  
        <v-divider></v-divider>

        ...
  </v-app>
</template>
  • <v-list-item-avatar>: 사용자 아바타/이미지를 표시하는 태그
    • <v-img>: 이미지 표시 태그
  • <v-list-item-title>: 리스트의 제목을 표시하는 태그로 사용자 이름을 표시하는 목적으로 사용 
  • <v-list-item-subtitle>: 리스트의 소제목을 표시하는 태그로 사용자의 로그인 계정을 표시하는 목적으로 사용
  • <v-divider>: 영역의 구분선을 표시하는 태그

 

본 게시글에서 작성한 코드 전체를 보고싶으시다면 아래 더보기를 참고해주세요.

더보기
<template>
  <v-app>
    <v-navigation-drawer app>
      <v-list dense>
        <!-- User(Employee) information -->
        <v-list-item>
          <v-list-item-avatar>
            <v-img src="https://cdn.vuetifyjs.com/images/john.png"></v-img>
          </v-list-item-avatar>
        </v-list-item>
        <v-list-item link>
          <v-list-item-content>
            <v-list-item-title class="text-h6">Sylvia Park</v-list-item-title>
            <v-list-item-subtitle>ardiums@gmail.com</v-list-item-subtitle>
          </v-list-item-content>
        </v-list-item>  
        <v-divider></v-divider>

        <!-- Menu/Navigation Bar list -->
        <v-list-item-group v-model="selectedItem" color="primary">
          <v-list-item v-for="(item, i) in navBasicItems" :key="i">
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>

          <v-divider></v-divider>

          <v-subheader>User Web</v-subheader>
          <v-list-item v-for="(item, i) in navUserWebItems" :key="i">
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
          
          <v-divider></v-divider>
          
          <v-subheader>Admin Web</v-subheader>
          <v-list-item v-for="(item, i) in navAdminWebItems" :key="i">
            <v-list-item-icon>
              <v-icon v-text="item.icon"></v-icon>
            </v-list-item-icon>
            <v-list-item-content>
              <v-list-item-title v-text="item.text"></v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list-item-group>
      </v-list>
    </v-navigation-drawer>
  
    <v-app-bar app>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
    </v-app-bar>
  
    <v-main>
      <v-container fluid>
        <router-view></router-view>
      </v-container>
    </v-main>
  
    <v-footer app>
      <!-- -->
    </v-footer>
  </v-app>
</template>

<script>

export default {
  name: 'App',

  data: () => ({
    // For Menu/Navigation Bar
    selectedItem: 0,

    navBasicItems: [
      { text: 'Dashboard', icon: 'mdi-view-dashboard' },
      { text: 'Setting', icon: 'mdi-cog-outline' }
    ],
    navUserWebItems: [
      { text: 'Notice', icon: 'mdi-file-outline' },
      { text: 'User Management', icon: 'mdi-account' },
      { text: 'Menu Management', icon: 'mdi-lan-check' },
    ],
    navAdminWebItems: [
      { text: 'User Management', icon: 'mdi-account-supervisor-circle' },
      { text: 'Rights Management', icon: 'mdi-lock-open' },
    ]
  }),
};
</script>

References

 

 

 

댓글