IT Study./VF

21. Vue와 Firebase로 나만의 사이트 만들기 - 하위메뉴 추가하기

impnem 2022. 5. 14. 20:56

 

 

 

VF - 21강

 

 

 


  • 이번 강에서는 하위 메뉴를 추가할 것이다.
  • 하지만 하위 메뉴에 추가하기가 들어가면 코드가 난잡해서 코딩하기가 쉽지 않아진다.
  • 강의 자체도 작성된 코드를 설명하며 끝이났으며, 필자도 코드를 따라 적으면서 이해하였다.
  • 아래의 코드를 따라쳐보며 작성하자.
<!-- menuView.vue -->
<template>
  <div>
    <v-list-item>
      <v-list-item-content>
        <v-list-item-title class="text-h6">
          Menu
        </v-list-item-title>
        <v-list-item-subtitle>
          0.0.1
        </v-list-item-subtitle>
      </v-list-item-content>
    </v-list-item>

    <v-divider></v-divider>
    <v-list>
      <!-- 메인 아이템 불러오기 -->
      <v-list-group
        v-for="(item, i) in items"
        :key="i"
        v-model="item.active"
        :prepend-icon="item.icon"
        no-action
      >
        <template v-slot:activator>
          <v-list-item-content>
            <v-list-item-title>
              {{ item.title }}
              <v-btn @click="openDialogItem(i)" icon><v-icon>mdi-pencil</v-icon></v-btn>
            </v-list-item-title>
          </v-list-item-content>
        </template>

        <!-- 서브 아이템 불러오기 -->
        <v-list-item
          v-for="(subItem, j) in item.subItems"
          :key="j"
          :to="subItem.to"
        >
          <v-list-item-content>
            <v-list-item-title>
              {{ subItem.title }}
              <v-btn @click="openDialogSubItem(i, j)" icon><v-icon>mdi-pencil</v-icon></v-btn>
            </v-list-item-title>
          </v-list-item-content>
        </v-list-item>

        <!-- 서브 아이템 추가하기 -->
        <v-list-item @click="openDialogSubItem(i, -1)">
          <v-list-item-icon>
            <v-icon>mdi-plus</v-icon>
          </v-list-item-icon>
          <v-list-item-content>
            <v-list-item-title>추가하기</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list-group>

      <!-- 메인 아이템 추가하기 -->
      <v-list-item @click="openDialogItem(-1)">
        <v-list-item-icon>
          <v-icon>mdi-plus</v-icon>
        </v-list-item-icon>
        <v-list-item-content>
          <v-list-item-title>추가하기</v-list-item-title>
        </v-list-item-content>
      </v-list-item>
    </v-list>

    <!-- 메인 아이템 수정 dialog -->
    <v-dialog v-model="dialogItem" max-width="400">
      <v-card>
        <v-card-title>
          메인 아이템 수정
          <v-spacer></v-spacer>
          <v-btn @click="saveItem" icon color="success"><v-icon>mdi-content-save</v-icon></v-btn>
          <v-btn @click="dialogItem=false" icon><v-icon>mdi-close</v-icon></v-btn>
        </v-card-title>
        <v-card-text>
          <v-row>
            <v-col cols="2">
              <v-icon v-text="formItem.icon" required></v-icon>
            </v-col>
            <v-col cols="10">
              <v-text-field
                v-model="formItem.icon"
                label="mdi icon"
                outlined
                clearable
                required
              ></v-text-field>
            </v-col>
          </v-row>
          <v-text-field v-model="formItem.title" label="아이템 이름" outlined hide-details></v-text-field>
        </v-card-text>
      </v-card>
    </v-dialog>

    <!-- 서브 아이템 수정 dialog -->
    <v-dialog v-model="dialogSubItem" max-width="400">
      <v-card>
        <v-card-title>
          서브 아이템 수정
          <v-spacer></v-spacer>
          <v-btn @click="saveSubItem" icon color=""><v-icon>mdi-content-save</v-icon></v-btn>
          <v-btn @click="dialogSubItem=false" icon><v-icon>mdi-close</v-icon></v-btn>
        </v-card-title>
        <v-card-text>
          <v-text-field v-model="formSubItem.title" label="메뉴 이름" outlined required></v-text-field>
          <v-text-field v-model="formSubItem.to" label="경로" outlined required></v-text-field>
        </v-card-text>
      </v-card>
    </v-dialog>
  </div>
</template>

<script>
export default {
  props: ['items'],
  data () {
    return {
      dialogItem: false,
      dialogSubItem: false,
      selectedItemIndex: 0, // 메인 아이템 제어용 변수
      selectedSubItemIndex: 0, // 서브 아이템 제어용 변수
      formItem: {
        icon: '',
        title: ''
      },
      formSubItem: {
        title: '',
        to: ''
      }
    }
  },
  methods: {
    async save () { // 전체 저장 함수
      try {
        const db = this.$firebaseDB.getDatabase()
        await this.$firebaseDB.set(this.$firebaseDB.ref(db, 'site/'), { // 통째로 하기 때문에 update대신 set 사용
          menu: this.items
        })
      } finally {
        this.dialogItem = false // 메인 아이템 저장 후 창 닫기
        this.dialogSubItem = false // 서브 아이템 저장 후 창 닫기
      }
    },
    openDialogItem (index) { // 메인 아이템 dialog 함수
      this.selectedItemIndex = index // 클릭한 dialog에 대한 index 기억하기
      console.log(index)
      if (index < 0) {
        this.formItem.icon = 'mdi-crosshairs-question' // 새로 메뉴를 만들다면 비워두기
        this.formItem.title = '' // 새로 메뉴를 만들다면 비워두기
      } else {
        this.formItem.icon = this.items[index].icon // 기존 메뉴라면 아이콘 이름 가져오기
        console.log(this.items[index].icon)
        this.formItem.title = this.items[index].title // 기존 메뉴라면 메뉴 이름 가져오기
      }
      this.dialogItem = true
    },
    async saveItem () { // 메인 아이템 저장 함수
      if (this.selectedItemIndex < 0) {
        this.items.push(this.formItem) // 현재 작성한 내용을 추가
      } else {
        this.items[this.selectedItemIndex].icon = this.formItem.icon // 현재 아이콘 가져오기
        this.items[this.selectedItemIndex].title = this.formItem.title // 현재 제목 가져오기
      }
      this.save()
    },
    openDialogSubItem (index, subIndex) { // 서브 아이템 dialog 함수
      this.selectedItemIndex = index // 클릭한 dialog에 대한 index 기억하기
      this.selectedSubItemIndex = subIndex // 클릭한 dialog에 대한 subIndex 기억하기
      if (subIndex < 0) {
        this.formSubItem.title = '' // 새로 서브 메뉴를 만들다면 비워두기
        this.formSubItem.to = '' // 새로 서브 메뉴를 만들다면 비워두기
      } else {
        this.formSubItem.title = this.items[index].subItems[subIndex].title // 기존 서브 메뉴라면 메뉴명 가져오기
        this.formSubItem.to = this.items[index].subItems[subIndex].to // 기존 서브 메뉴라면 경로 가져오기
      }
      this.dialogSubItem = true
    },
    async saveSubItem () { // 서브 아이템 저장 함수
      if (this.selectedSubItemIndex < 0) {
        if (!this.items[this.selectedItemIndex].subItems) {
          this.items[this.selectedItemIndex].subItems = []
        }
        this.items[this.selectedItemIndex].subItems.push({ title: this.formSubItem.title, to: this.formSubItem.to }) // 현재 작성한 내용을 추가
      } else {
        this.items[this.selectedItemIndex].subItems[this.selectedSubItemIndex].title = this.formSubItem.title // 현재 아이콘 가져오기
        this.items[this.selectedItemIndex].subItems[this.selectedSubItemIndex].to = this.formItem.to // 현재 경로 가져오기
      }
      this.save()
    }
  }
}
</script>

<style>

</style>

 

  • 코드가 점점 난잡해지고 있으나 어떻게 돌아가는지 이해하고 넘어가도록 하자.

 

 

21 하위메뉴 추가하기 : memi

하위메뉴 추가는 결국 상위메뉴와 같은 방법이지만..\n코드가 길어져서 가독성이 떨이지므로 코딩이 쉽지는 않습니다.\n코드를 보며 직접 만들어보며 감

memi.dev

 

 

 


해당 글은 [memi dev] 유튜브 채널을 토대로 공부한 내용을 기록하기 위하여 작성됨.