IT Study./VF

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

impnem 2022. 5. 13. 19:53

 

 

 

VF - 20강

 

 

 


  • 이번 강에서는 메뉴를 추가하는 기능을 넣어볼 것이다.
  • 일단 그전에 수정 기능과 추가 기능을 넣으려면 Navigation drawer가 지금보다 넓어야 한다.
  • 그래서 App.vue 파일의 <v-navigation-drawer> 태그에 아래와 같이 width 속성을 추가한다.
<!-- App.vue -->
<v-navigation-drawer app v-model="drawer" width="400">
  <site-menu :items="site.menu"></site-menu>
</v-navigation-drawer>

 

  • 그리고 최종적으로 만들어질 메뉴는 상위 메뉴와 하위 메뉴로 만들어지기 때문에 menuView.vue 파일에 메뉴 관련 코드 중 하위 메뉴 관련 코드를 아래와 같이 수정한다.
    • 항상 타이틀이 겹치면 문제가 되기 때문에 하위 메뉴인 subItem도 상위 메뉴인 item과 같이 변경해야 한다.
<!-- menuView.vue -->
<v-list-item
  v-for="(subItem, j) in item.subItems"
  :key="j"
  :to="subItem.to"
>
  • 그리고 상위 메뉴 추가하기가 생성되어야 할 부분은 상위 메뉴인 i와 하위 메뉴인 j가 for문으로 순차적으로 다 돈 후 끝나는 순간에 생성되어야 하기 때문에 상위 메뉴가 끝나는 태그인 </v-list-group>의 뒤가 된다.
  • 그 뒤에는 아래의 코드가 추가된다.
  <!-- menuView.vue -->
  <v-list-item>
    <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>가 끝나는 지점에 추가한다.
  <!-- menuView.vue -->
  <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 v-text="item.title"></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 v-text="subItem.title"></v-list-item-title>
      </v-list-item-content>
    </v-list-item>
    <v-list-item> <!-- 서브메뉴 추가 -->
      <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>
  • 결과 화면은 아래와 같다.

 

  • 이제 추가하기 버튼을 누르면 추가가 될 수 있도록 할 것인데 이것은 dialog로 구현할 것이다.
  • 상위 메뉴 추가와 하위 메뉴 추가를 하기 위해서는 dialog가 2개가 필요하다. 그래서 아래와 같은 코드를 추가한다.
<!-- menuView.vue -->
<template>
  <div>

    <v-list>
     ...
    </v-list>
    <!-- dialog 추가 -->
    <v-dialog v-model="dialogItem" max-width="400">
      <v-card>
        <v-card-title>
          수정하기
          <v-spacer></v-spacer>
          <v-btn icon><v-icon>mdi-content-save</v-icon></v-btn>
        </v-card-title>
        <v-card-text>
          <v-text-field v-model="formItem.title"></v-text-field>
        </v-card-text>
      </v-card>
    </v-dialog>
    
  </div>
</template>

<script>
export default {
  props: ['items'],
  data () {
    return {
      dialogItem: false, // 상위 메뉴용
      dialogSubItem: false, // 하위 메뉴용
      formItem: {
        icon: '',
        title: ''
      }
    }
  }
}
</script>

<style>
</style>
  • 그리고 이 dialog는 추가하기 버튼을 클릭하면 떠야하므로 먼저 상위 메뉴 추가하기 코드에 클릭 이벤트를 아래와 같이 추가한다.
  <!-- menuView.vue -->
  <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>
  • openDialogItem(-1)라는 함수를 사용한 이유는 상위 메뉴 추가는 물론이고 상위 메뉴를 수정할 수도 있기 때문에 true, false가 아닌 index로 넣어 dialog를 재사용하기 위함이다. -1은 메뉴가 없는 상태를 뜻한다.
  • 그리고 methods에 openDialogItem함수를 아래와 같이 정의한다.
<!-- menuView.vue -->
<script>
export default {
  props: ['items'],
...
  methods: {
    openDialogItem (index) {
      this.dialogItem = true
    }
  }
}
</script>

 

  • 기존 메뉴에 수정 버튼을 아래와 같이 추가한다.
<!-- menuView.vue -->
<template v-slot:activator>
  <v-list-item-content>
    <v-list-item-title v-text="item.title"></v-list-item-title>
  </v-list-item-content>
  <v-list-item-action> <!-- 수정버튼 추가 -->
    <v-btn @click="openDialogItem(i)" icon><v-icon>mdi-pencil</v-icon></v-btn>
  </v-list-item-action>
</template>
  • <v-list-item-action> 태그를 사용하면 하단의 뒤쪽으로 붙게 된다.
  • 지금까지 결과 화면은 아래와 같다.

 

  • 추가하고 수정하는 버튼을 하나로 한다면 제어용 변수가 또 필요하므로 아래와 같이 추가한다.
<!-- menuView.vue -->
<script>
export default {
  props: ['items'],
  data () {
    return {
      dialogItem: false,
      dialogSubItem: false,
      formItem: {
        icon: '',
        title: ''
      },
      selectedItemIndex: -1 // 제어용 변수 추가
    }
  }
}
</script>

 

  • 그리고 openDialogItem 함수에 위에서 추가한 제어용 변수를 아래와 같이 추가한다.
// menuView.vue
openDialogItem (index) {
  this.selectedItemIndex = index
  this.dialogItem = true
  if (index < 0) {
    this.formItem.title = '' // 새로 만든다면 비워두기
  } else {
    this.formItem.title = this.items[index].title // 기존 메뉴라면 메뉴이름 가져오기
  }
}

 

  • 다음으로 이제 추가하거나 수정했을 때 save를 해야 한다.
  • 그래서 저장 버튼을 클릭했을 때 저장되도록 아래의 코드를 추가한다.
<!-- menuView.vue -->
<v-dialog v-model="dialogItem" max-width="400">
  <v-card>
    <v-card-title>
      수정하기
      <v-spacer></v-spacer>
      <v-btn icon @click="saveItem"><v-icon>mdi-content-save</v-icon></v-btn> <!-- 클릭 이벤트 추가 -->
    </v-card-title>
    <v-card-text>
      <v-text-field v-model="formItem.title"></v-text-field>
    </v-card-text>
  </v-card>
</v-dialog>

<script>
export default {
  props: ['items'],
...
  methods: {
   ...
    saveItem () {
      if (this.selectedItemIndex < 0) {
        this.items.push(this.formItem) // 현재 작성한 내용을 추가
      } else {
        this.items[this.selectedItemIndex] = this.formItem // 현재 내용 가져오기
      }
      this.save()
    },
    async save () {
      try {
        const db = this.$firebaseDB.getDatabase()
        await this.$firebaseDB.update(this.$firebaseDB.ref(db, 'site/'), {
          menu: this.items // 메뉴 통째로 저장
        })
      } finally {
        this.dialogItem = false // 저장 후 창 닫기
      }
    }
  }
}
</script>
  • 이제 메뉴를 추가하거나 수정이 가능하지만 아직 아이콘은 없다.
  • test11라는 이름을 가지는 메뉴를 추가했을 경우 결과 화면은 아래와 같다.
    • 만약 Realtime DB에 write가 false가 되어있다면 true로 바꾸길 바란다.

  • 위처럼 서버에도 저장된 것을 확인할 수 있다.
  • 강의에서는 코드를 나중에 한꺼번에 보여준다고 한다. 그 이유는 단순작업이 많이 필요하여 시간이 부족하기 때문이다.

 

  • 이번 강의에서는 이런 식으로 제어를 한다는 것 정도만 알고 넘어가자.

 

 

20 메뉴 추가하기 : memi

firebase realtime을 이용해서 메뉴를 추가해봅니다.\n- - - \n# 코드\n## views/site/menu.vue\n```vue\n<t

memi.dev

 

 

 


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