vue

 

 

vue 

프로젝트 초기 생성 방법은

다음을 참조 : https://macaronics.net/m04/vue/view/2048

 

 

 

소스 :

https://github.com/braverokmc79/vue-todo

 

 

 

1. 파이어 베이스 DB와 연동하지 않은 프로젝트

 

최종 산출물

 

 

 

vuetify 사용법

 

https://vuetifyjs.com/en/

예를 들엇 v-card 를 찾아서 적용하고 싶다면 검색을 한다.

 

 

vuetifyjs 에서 v-card 검색 후

 

 

 

 

이와 같은 방법으로

 

v-card, 

v-row

cols,

v-list-item

v-text-field

 

등의 검색을 하고 예시로 사용한 템플릿 소스를 보면서  적용한다.

 

 

 

 

https://vuetifyjs.com/en/components/checkboxes/

 

 

 

App.vue

<template>
  <v-app>
     <v-card>
        <v-app-bar dark color="pink">
          <v-app-bar-nav-icon></v-app-bar-nav-icon>
          <v-toolbar-title>To-Do 리스트</v-toolbar-title>
        </v-app-bar>

      <v-main>
          <v-container>
             <v-row my-5>
                <v-col cols="8"  offset="1"  >
                    <!-- 실행되자마자 입력 포커스를 가지도록 autofocus 설절 -->
                    <v-text-field   label="할 일" required autofocus v-model="sTodoTitle"  >   
                    </v-text-field>       
                </v-col>
                <v-col cols="2">
                  <v-btn  fab class="mx-2"  dark   color="pink"  @click="fnsubmitTodo()" >
                    <v-icon dark>mdi-plus</v-icon>
                  </v-btn>
                </v-col>
             </v-row>


             <v-row>
                <v-col cols="12" >

                  <v-list two-line  v-for="(item, i) in items"  :key="i">
            
                        <v-card flat color="grey lighten-3"  v-if="!item.b_edit">
                            <v-list-item-group>
                              <v-list-item class="py-2">
                                <template >
                                  <v-list-item-action>
                                    <v-checkbox v-model="item.b_completed"  @change="fnCheckboxChange(item.key)"></v-checkbox>
                                  </v-list-item-action>

                                  <v-list-item-content>
                                    <v-list-item-title v-text="item.todo_title" :class="{'style_completed':item.b_completed}"></v-list-item-title>
                                    <v-list-item-subtitle class="mt-2">

                                        <v-icon class="pointer" @click="fnSeEditTodo(item.key)">create</v-icon>
                                        <v-icon class="pointer" @click="fnRemoveTodo(item.key)">delete</v-icon>

                                    </v-list-item-subtitle>
                                  </v-list-item-content>
                                </template>
                              </v-list-item>
                            </v-list-item-group>  
                      </v-card>


                      <v-card v-else dark>
                            <v-list-item-group>
                              <v-list-item class="py-2">
                                
                                <template v-slot:default="{ active }">
                                  <v-list-item-action>
                                    <v-checkbox v-model="item.b_completed"  @change="fnCheckboxChange(item.key)"></v-checkbox>
                                  </v-list-item-action>

                                  <v-list-item-content >

                                    <v-col cols="11"   >
                                        <v-text-field v-model="item.todo_title"   color="blue darken-2"  autofocus clearable   
                                          required
                                        ></v-text-field>
                                  
                                    </v-col>
                                    <v-col cols="1"   >
                                      <v-list-item-subtitle class="mt-2">
                                        <v-icon class="pointer" @click="fnSaveEditTodo(item.key)">save</v-icon>
                                        <v-icon class="pointer" @click="fnCancelEdit(item.key)">cancel</v-icon>
                                      </v-list-item-subtitle>
                                    </v-col>

                                  </v-list-item-content>



                                </template>
                              </v-list-item>
                            </v-list-item-group>  
                      </v-card>




                  </v-list>
                </v-col>
                
             </v-row>



          </v-container>
      </v-main>
  </v-card> 
  </v-app>
</template>

<script>

export default {
  name: 'App',

  data () {
    return {
       sTodoTitle:"",
       selectedItem: 1,

       items: [
        {key:1, todo_title: 'Real-Time' , b_edit:false, b_completed:false},
        {key:2, todo_title: 'Audience' , b_edit:false , b_completed:false},
        {key:3, todo_title: 'Conversions' , b_edit:false, b_completed:false},
        {key:4, todo_title: 'Conversions' , b_edit:true, b_completed:false},
      ],
      checkbox: true,
      settings: [], 

      }
     
  },
  methods: {
    //할일 추가 폼 버튼 클릭시
    fnsubmitTodo(){
      if(!this.sTodoTitle){
        window.alert("할일을 입력해 주세요.");
        return;
      }
      const data= {
            key:new Date().getTime(), 
            todo_title:this.sTodoTitle ,
            b_edit:false, 
            b_completed:false
          }
      this.items.push(data);
      this.sTodoTitle="";
    },
    

    //수정 버튼 클릭시
    fnSeEditTodo(key){
      this.items.map(item=>{
          if(item.key===key){
            item.b_edit=true
          }
      });
    },

    //수정후 저저장 버튼 클릭시
    fnSaveEditTodo(key){
      
      this.items.map(item=>{
          if(item.key===key){
            item.b_edit=false
          }
      });
    },


    //취소버튼 클릭시
    fnCancelEdit(key){
      this.items.map(item=>{
          if(item.key===key){
            item.b_edit=false
          }
      });
    },

    //삭제 버튼 클릭시
    fnRemoveTodo(key){
  
      const result=this.items.filter((item)=>(item.key!==key));   
      this.items=result;

    },


    fnCheckboxChange(key){
       
    }

  },
  computed: {
    
  },
};
</script>

<style>
  .pointer {
    /* 마우스포인터를 손모양으로 변경 */
    cursor: pointer;
  }

  .style_completed {
    /* 할 일의 제목을 취소선으로 변경 */
    text-decoration: line-through;
  }
</style>

 

 

 

 

 

 

 

 

 

2. vue 파이어 베이스 실시간 데이터 베이스  3분안에  연동 ,

파이어 베이스 DB 준비하기

 

파이어베이스 공식 문서 참조

 

https://firebase.google.com/docs/database/web/start?hl=ko

 

 

파이어베이스 실시간 데이터 베이스 설정

 

다음과 같이 데이터 베이스 만들기를 클릭한다

 

 

데이터 베이스 지역  설정

 

 

테스트모드에서 시작 설정

 

 

 

위와 같이 하면 파이어베이스 실시간 데이터 베이스 설정 완료 된 것이다.

 

 

 

 

 

다음을 통해   databaseURL 값을  알아내야 한다.

 

 

 

다음 톱니바퀴  버튼을 클릭후 맨 아래로 내리면 

 

 

 

파이어베이스  SDK 설정  및  구성 값을 알아 낼 수 있다.

 

 

 

 

 

 

src/datasources/firebase.js 을 생성후 다음과 같이 작성

// 파이어베이스 앱 객체 모듈 가져오기
import firebase from 'firebase/compat/app'
// 파이어베이스 패키지 모듈 가져오기
import 'firebase/compat/database';

// 파이어베이스 DB를 초기화하고 연결
const oDB = firebase.initializeApp({
  // 파이어베이스 콘솔에서 복사하여 붙여넣기
  //databaseURL: "https://pwa-to-do.firebaseio.com",
  databaseURL: "https://pwa-to-do-33db2.firebaseio.com",
}).database();

// 파이어베이스 DB객체 중에서 todos 항목을 다른 곳에서 사용하도록 공개
export const oTodosinDB = oDB.ref('todos');

 

 

 

src/main.js    에서 다음 과 같이 수정한다.

import Vue from "vue";
import App from "./App.vue";
import "./registerServiceWorker";
import vuetify from "./plugins/vuetify";

//뷰파이어 노드 모듈 가져와서 Vue 에 연결
import { rtdbPlugin } from "vuefire";
Vue.use(rtdbPlugin);

Vue.config.productionTip = false;

new Vue({
  vuetify,
  render: (h) => h(App),
}).$mount("#app");

 

뷰파이어 연결

뷰파이어를 사용하면 파이어베이스의 RTDB(realtime database) 와 파이어스토어 (클라우드 스토어 ) 등 두가지 DB 형식을 뷰 애플리케이션과 연결할 수 있도록 돕는

플러그인을 제공한다. 

여기서는 RTDB 를 사용할 것이므로 rtdbplugin 을 모듈을 가져와서 뷰어 연결한다.

 

 

 

 

 

 

oTodosinDB는 루트 노드이고 child(pKey) 를 사용하면 원하는 자식 노드를 바로 선택할 수있다.

 

 

 

 

 

 

 

 

 

 

 

 

1) 파이어베이스 DB 가져오기

//파이어베이스 DB 가져옴
import { oTodosinDB } from './datasources/firebase';

 

2) 목록 불러오기

    data () {
      return {
        oTodos:[], //할일 데이터 목록 저장 변수
        sTodoTitle:"", //할일 제목 저장 문자열 변수

        // items: [
        //   {key:1, todo_title: 'Real-Time' , b_edit:false, b_completed:false},
        //   {key:2, todo_title: 'Audience' , b_edit:false , b_completed:false},
        //   {key:3, todo_title: 'Conversions' , b_edit:false, b_completed:false},
        //   {key:4, todo_title: 'Conversions' , b_edit:true, b_completed:false},
        // ],

        }
    },

    //파이어베이스를 쉽게 사용하도록 oTodos 변수로 변경
    firebase:{
      oTodos:oTodosinDB
    },

 

 

3)등록하기

      //할일 추가 폼 버튼 클릭시
      fnsubmitTodo(){
        if(!this.sTodoTitle){
          window.alert("할일을 입력해 주세요.");
          return;
        }

        //할일 제목 , 완료 수정 모드 상탯값을 파이어베이스 DB 에 저장
        oTodosinDB.push({
          todo_title: this.sTodoTitle,
          b_completed: false,
          b_edit: false
        });
        this.sTodoTitle="";
      },

 

 

 

4) 수정하기

      //수정 - 수정후 저저장 버튼 클릭시
      fnSaveEditTodo(pItem){
        const sKey=pItem['.key']

        oTodosinDB.child(sKey).set({
          todo_title:pItem.todo_title,
          b_completed:pItem.b_completed,
          b_edit:false
        });

      },

 

 

 

 

5)삭제하기

 //삭제 - 삭제 버튼 클릭시
      fnRemoveTodo(key){
        //전달된 할일 DB 에서 제거
        oTodosinDB.child(key).remove();
      },

 

 

 

 

전체 코드

App.vue

  <template>
    <v-app>
      <v-card>
          <v-app-bar dark color="pink">
            <v-app-bar-nav-icon></v-app-bar-nav-icon>
            <v-toolbar-title>To-Do 리스트</v-toolbar-title>
          </v-app-bar>

        <v-main>
            <v-container>
              <v-row my-5>
                  <v-col cols="8"  offset="1"  >
                      <!-- 실행되자마자 입력 포커스를 가지도록 autofocus 설절 -->
                      <v-text-field   label="할 일" required autofocus v-model="sTodoTitle"  >   
                      </v-text-field>       
                  </v-col>
                  <v-col cols="2">
                    <v-btn  fab class="mx-2"  dark   color="pink"  @click="fnsubmitTodo()" >
                      <v-icon dark>mdi-plus</v-icon>
                    </v-btn>
                  </v-col>
              </v-row>


              <v-row>
                  <v-col cols="12" >

                    <v-list two-line  v-for="(item, i) in oTodos"  :key="i">
              
                          <v-card flat color="grey lighten-3"  v-if="!item.b_edit">
                              <v-list-item-group>
                                <v-list-item class="py-2">
                                  <template >
                                    <v-list-item-action>
                                      <v-checkbox v-model="item.b_completed"  @change="fnCheckboxChange(item)"></v-checkbox>
                                    </v-list-item-action>

                                    <v-list-item-content>
                                      <v-list-item-title v-text="item.todo_title" :class="{'style_completed':item.b_completed}"></v-list-item-title>
                                      <v-list-item-subtitle class="mt-2">

                                          <v-icon class="pointer" @click="fnSetEditTodo(item['.key'])">create</v-icon>
                                          <v-icon class="pointer" @click="fnRemoveTodo(item['.key'])">delete</v-icon>

                                      </v-list-item-subtitle>
                                    </v-list-item-content>
                                  </template>
                                </v-list-item>
                              </v-list-item-group>  
                        </v-card>


                        <v-card v-else dark>
                              <v-list-item-group>
                                <v-list-item class="py-2">
                                  
                                  <template v-slot:default="{ active }">
                                    <v-list-item-action>
                                      <v-checkbox v-model="item.b_completed"  @change="fnCheckboxChange(item)"></v-checkbox>
                                    </v-list-item-action>

                                    <v-list-item-content >

                                      <v-col cols="11"   >
                                          <v-text-field v-model="item.todo_title"   color="blue darken-2"  autofocus clearable   
                                            required
                                          ></v-text-field>
                                    
                                      </v-col>
                                      <v-col cols="1"   >
                                        <v-list-item-subtitle class="mt-2">
                                          <v-icon class="pointer" @click="fnSaveEditTodo(item)">save</v-icon>
                                          <v-icon class="pointer" @click="fnCancelEdit(item['.key'])">cancel</v-icon>
                                        </v-list-item-subtitle>
                                      </v-col>

                                    </v-list-item-content>



                                  </template>
                                </v-list-item>
                              </v-list-item-group>  
                        </v-card>




                    </v-list>
                  </v-col>
                  
              </v-row>



            </v-container>
        </v-main>
    </v-card> 
    </v-app>
  </template>

  <script>
//파이어베이스 DB 가져옴
import { oTodosinDB } from './datasources/firebase';

console.log(" oTodosinDB  : " ,oTodosinDB);
  export default {
    name: 'App',
    


    data () {
      return {
        oTodos:[], //할일 데이터 목록 저장 변수
        sTodoTitle:"", //할일 제목 저장 문자열 변수

        // items: [
        //   {key:1, todo_title: 'Real-Time' , b_edit:false, b_completed:false},
        //   {key:2, todo_title: 'Audience' , b_edit:false , b_completed:false},
        //   {key:3, todo_title: 'Conversions' , b_edit:false, b_completed:false},
        //   {key:4, todo_title: 'Conversions' , b_edit:true, b_completed:false},
        // ],

        }
    },

    //파이어베이스를 쉽게 사용하도록 oTodos 변수로 변경
    firebase:{
      oTodos:oTodosinDB
    },

    methods: {
      //할일 추가 폼 버튼 클릭시
      fnsubmitTodo(){
        if(!this.sTodoTitle){
          window.alert("할일을 입력해 주세요.");
          return;
        }
        // const data= {
        //       key:new Date().getTime(), 
        //       todo_title:this.sTodoTitle ,
        //       b_edit:false, 
        //       b_completed:false
        //     }
        // this.items.push(data);

        //할일 제목 , 완료 수정 모드 상탯값을 파이어베이스 DB 에 저장
        oTodosinDB.push({
          todo_title: this.sTodoTitle,
          b_completed: false,
          b_edit: false
        });
        this.sTodoTitle="";
      },
      

      //수정 버튼 클릭시
      fnSetEditTodo(key){
        // this.items.map(item=>{
        //     if(item['.key']===key){
        //       item.b_edit=true
        //     }
        // });
        oTodosinDB.child(key).update({
            b_edit:true
        })
      },

      //수정 - 수정후 저저장 버튼 클릭시
      fnSaveEditTodo(pItem){
        // this.items.map(item=>{
        //     if(item['.key']===key){
        //       item.b_edit=false
        //     }
        // });
        const sKey=pItem['.key']

        oTodosinDB.child(sKey).set({
          todo_title:pItem.todo_title,
          b_completed:pItem.b_completed,
          b_edit:false
        });

      },


      //취소버튼 클릭시
      fnCancelEdit(key){
        // this.items.map(item=>{
        //     if(item['.key']===key){
        //       item.b_edit=false
        //     }
        // });
        oTodosinDB.child(key).update({
            b_edit:false
        })
      },

      //삭제 - 삭제 버튼 클릭시
      fnRemoveTodo(key){
        // const result=this.items.filter((item)=>(item['.key']!==key));   
        // this.items=result;

        //전달된 할일 DB 에서 제거
        oTodosinDB.child(key).remove();
      },

      //체크박스 선택 되면 DB 에 b_completed 변경값 저장
      fnCheckboxChange(pItem){
        const sKey =pItem['.key']
        oTodosinDB.child(sKey).update({
          b_completed:pItem.b_completed
        })
      }

    },


    mounted() {
      document.title = 'Todo 할일'
    }
  };
  </script>

  <style>
    .pointer {
      /* 마우스포인터를 손모양으로 변경 */
      cursor: pointer;
    }

    .style_completed {
      /* 할 일의 제목을 취소선으로 변경 */
      text-decoration: line-through;
    }
  </style>

 

 

 

 

 

 

 

수정모드에서  set() 함수와 update() 함수 차이

수정 모드에서 수정한 내용을 저장하려면 update() 함수가 아니라 set() 함수를 사용한다.

그 이유는 set() 함수는 update() 함수와 달리 하위 노드도 모두 영향을 주는 , 좀 더 큰 수정 기능이기 때문이다.

 

 

    //수정 - 수정후 저저장 버튼 클릭시
      fnSaveEditTodo(pItem){

        const sKey=pItem['.key']

        oTodosinDB.child(sKey).set({
          todo_title:pItem.todo_title,
          b_completed:pItem.b_completed,
          b_edit:false
        });

      },


      //취소버튼 클릭시
      fnCancelEdit(key){

        oTodosinDB.child(key).update({
            b_edit:false
        })
      },

 

 

 

 

 

 

 

 

 

 

 

about author

PHRASE

Level 60  라이트

산밑 집에 방앗공이 놀다 , 그 고장의 산물이 오히려 그 곳에서는 귀하다는 말.

댓글 ( 4)

댓글 남기기

작성