Vue, Google Firestore 및 Google 인증이 포함된 간단한 Todo 애플리케이션

63074 단어

소개하다.


나는 의미 있는 프로젝트를 통해 모든 프로그래밍 언어를 배우는 것이 가장 빠르고 간단하다는 것을 발견했다.진실한 프로젝트를 함으로써 당신은 디자인에서 이익을 얻고 처음부터 끝까지 프로젝트를 관리할 수 있습니다.본고에서 우리는 Vue를 사용하여 하나의 응용 프로그램을 구축하고 Vuex를 사용하여 Vue 응용 프로그램의 상태 관리를 배울 것이다.
우리는 본문에서 다음과 같은 내용을 배울 것이다
  • Vue CLI(버전 2)를 사용한 프로젝트 생성
  • Vue 구성 요소 생성 및 사용
  • 부트 Vue를 사용하여 구성 요소 스타일 설정
  • Vuex를 사용한 상태 관리
  • Google Firebase 인증
  • 을 사용한 인증
  • 구글 파이어 상점의 때 묻은 사건
  • 소스 코드


    GitHub에서 전체 소스 코드를 찾을 수 있습니다.

    선결 조건

  • Visual Studio 코드(VS 코드) here에서 설치
  • 부터here 설치 노드
  • 부터 here Vue CLI 설치
  • npm install -g @vue/cli
    

    프로젝트 만들기


    컴퓨터에 Vue 명령줄 인터페이스(CLI)가 설치되어 있는지 확인합니다.terminal 명령에서 다음 명령을 실행하여 Vue CLI 설치 가능
    todo 프로그램 프로젝트 만들기
    vue create todo-app
    
    위 명령은 todo-app라는 새 Vue 프로젝트를 만듭니다.
    디렉토리를 새 항목으로 변경
    cd todo-app
    
    Vuex 설치
    npm install vuex --save
    
    Vue 부트 설치
    npm install bootstrap bootstrap-vue --save
    
    Firebase 설치
    npm install firebase --save
    

    개발을 위해 컴파일하고 다시 불러오기


    npm run serve
    

    생산을 위해 편역하고 축소하다


    npm run build
    

    Lints 및 fixes 파일


    npm run lint
    

    사용자 정의 구성


    참조Configuration Reference.

    VS 코드에서 항목 열기


    VS 코드에서 항목 열기
    code .
    
    Vue CLI 에서 생성되는 기본 파일 구조를 볼 수 있습니다.

    HelloWorld는 삭제합니다.vue 구성 요소.잠시 후에 구성 요소를 추가할 것입니다.
    결합키(Ctrl+J 또는 CMD+J)를 눌러 VS 코드에서 터미널 열기

    Firebase를 만듭니다.js


    Firebase는 인증 및 데이터베이스 이벤트(CRUD)를 제공합니다.
    Firebase 항목이 Google Firebase에서 구성되었는지 확인하십시오.
    현재 firebase.js 디렉터리에 src라는 새 파일을 만듭니다.
    다음 코드를 파일로 복사합니다
    import firebase from 'firebase';
    // For Firebase JS SDK v7.20.0 and later, measurementId is optional
    const firebaseConfig = {
      // Add your firebase config here
    };
    
    const firebaseapp = firebase.initializeApp(firebaseConfig);
    
    // database
    const db = firebaseapp.firestore();
    
    // authentication
    const auth = firebase.auth();
    const provider = new firebase.auth.GoogleAuthProvider();
    
    export { auth, provider };
    export default db;
    
    자체 소프트웨어로 구성을 수정했는지 확인하십시오firebaseConfig.

    상태 관리를 위한 스토리지 객체 만들기


    모든 상태가 원본 (src) 디렉터리에 있는store 디렉터리에 있기를 바랍니다.
    현재 우리는 src 폴더 아래에 store라는 새 폴더를 만듭니다.

    사용자 상태 생성(스토리지)


    사용자 상태 Google Firebase를 사용하여 로그인/로그아웃한 사용자를 관리합니다.로그인하거나 로그아웃한 사용자를 제어합니다.사용자 인터페이스는 사용자 상태에 따라 업데이트됩니다.
    store 디렉토리에 user.js라는 새 JavaScript 파일을 만듭니다.
    다음 코드를 파일로 복사합니다
    const state = {
      user: null
    };
    
    const getters = {
      user: state => state.user
    };
    
    const actions = {
      signIn ({commit}, user) {
        commit('signIn', user);
      },
      signOut({commit}) {
        commit('signOut');
      }
    };
    
    const mutations = {
      signIn: (state, user) => {
        state.user = user;
      },
      signOut: state => state.user = null
    };
    
    export default {
      state,
      getters,
      actions,
      mutations
    };
    

    업무 상태 만들기(스토어)


    todo state는 todo 목록과 todo 항목을 관리합니다.Todos 상태는
  • Google firestore 데이터베이스에서 데이터 로드
  • firestore 데이터베이스에 데이터 추가
  • 데이터를 Firestore 데이터베이스
  • 로 업데이트
  • firestore 데이터베이스
  • 에서 데이터 삭제
    store 디렉토리에 todos.js라는 새 JavaScript 파일을 만듭니다.
    다음 코드를 파일로 복사합니다
    import db from '../firebase'
    
    // State declaration
    const state = {
      /**
       * each todo item will have the format
       * {
       *  id: String,
       *  title: String,
       *  completed: Boolean
       * }
       */
      todos: []
    };
    
    // Getters
    const getters = {
      // Get all todo items in the current state
      allTodos: state => state.todos
    };
    
    // actions
    const actions = {
      /**
       * Loading todos   
       * This is fetch data from database
       */
      fetchTodos ({commit}, user) {        
        db.collection('user')
          .doc(user.uid)
          .collection('todos')
          .onSnapshot(snapshot => {
            commit('setTodos', snapshot.docs.map(doc => {
              return {
                id: doc.id,
                doc: doc.data()
              }
            }));
          })    
      },
      /**
       * Add a new todo action
       * This is fired when the user submit the form add a new todo 
       * @param {String} payload - The title string of the the new todo
       */
      addTodo({ commit}, payload) {
        const uid = payload.user.uid;
        const title = payload.title;
    
        const newtodo = {
          title,
          completed: false
        };
    
        db.collection('user')
          .doc(uid)
          .collection('todos')
          .add(newtodo)
          .then(docRef => {
            commit('addTodo', {
              id: docRef.id,
              data: newtodo
            });
          }) 
      },
      /**
       * Update the status of the todo item in the state
       * @param {Object} payload - The object contains
       * - the id to identify the todo item in the collection list
       * - completed property to update the status of the todo item
       */
      toggleCompleted ({commit}, payload) {
        const uid = payload.user.uid;
        const id = payload.id;
        const completed = payload.completed;
        db.collection('user')
          .doc(uid)
          .collection('todos')
          .doc(id)
          .update({
            completed: completed
          })
        commit('toggleCompleted', {
          id,
          completed
        });
      },
      /**
       * 
       * @param {*} param0 
       * @param {Number} payload - The number id to identify the todo item in the collection
       */
      deleteTodo ({commit}, payload) {
        const uid = payload.user.uid;
        const id = payload.id;
        db.collection('user')
          .doc(uid)
          .collection('todos')
          .doc(id)
          .delete();
        commit('deleteTodo', id);
      }
    };
    
    // mutations
    const mutations = {
      setTodos: (state, todos) => {    
        state.todos = todos.map(todo => {
          return {
            id: todo.id,
            title: todo.doc.title,
            completed: todo.doc.completed
          }
        });
      },
      addTodo: (state, {id, data}) => {      
        console.log('addTodo');
        const newtodo = {
          id,
          title: data.title,
          completed: data.completed
        };  
        const oldTodos = [...state.todos];
        const index = oldTodos.findIndex(todo => todo.id === id);    
        // adding new todo the list
        if (index < 0) {
          state.todos.unshift(newtodo); // = [newtodo, ...state.todos];
        }
    
        console.log(state.todos);
      },
      toggleCompleted: (state, {id, completed}) => {
        const index = state.todos.findIndex((todo) => todo.id === id);
        if (index >= 0) {
          state.todos[index].completed = completed;
        }
      },
      deleteTodo: (state, id) => {
        const index = state.todos.findIndex((todo) => todo.id === id);
        if (index >= 0) {
          state.todos.splice(index, 1);
        }
      }
    };
    
    export default {
      state,
      getters,
      actions,
      mutations
    };
    

    Vuex 스토어 만들기


    현재 우리는 usertodos의 상태가 있어서 상점 집합에서 그것들을 사용하고 싶다store.js 폴더 아래에 src라는 새 파일을 만듭니다.
    다음 코드를 파일로 복사합니다
    // Create a store
    import Vue from 'vue'
    import Vuex from 'vuex'
    import todos from './todos';
    import user from './user';
    
    Vue.use(Vuex);
    
    // create store
    export default new Vuex.Store({
      modules: {
        todos,
        user
      }
    });
    

    프로젝트에 스토리지 추가


    애플리케이션에 스토리지를 추가하려면 main.js를 엽니다.
    응용 프로그램에 추가를 유도할 것입니다
    import Vue from 'vue'
    import App from './App.vue'
    // Import store
    import store from './store/store'
    // Bootstrap
    import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
    
    // import bootstrap and BootstrapVue css
    import 'bootstrap/dist/css/bootstrap.css'
    import 'bootstrap-vue/dist/bootstrap-vue.css'
    
    Vue.use(BootstrapVue);
    Vue.use(IconsPlugin);
    
    Vue.config.productionTip = false;
    
    new Vue({
      render: h => h(App),
      store
    }).$mount('#app')
    

    어셈블리 생성


    지금 우리는 이미 준비가 다 되었다.응용 프로그램의 구성 요소를 만들기 시작합니다.우리 프로그램은 다음 구성 요소를 포함할 것입니다
  • Login 구성 요소 - 사용자 로그인 또는 로그아웃
  • 표시
  • NewTodo 구성 요소 - 새 업무 추가
  • 를 위한 폼 구성 요소
  • TodoList 구성 요소 - 각 업무 항목
  • 을 표시하는 목록 보기입니다.
  • TodoItem 구성 요소 - 표시할 업무
  • 로그인 구성 요소 생성


    component 폴더 아래에 새 파일을 만듭니다. Login.vue다음 스크립트를 이 파일로 복사합니다
    <template>
      <div class="login">
        <div @click="logout" v-if="user" class="logout">
          <b-avatar variant="info" :src="imageSrc" class="mr-3"></b-avatar>
          <span class="mr-auto">{{user.user.displayName}}</span>      
        </div>
        <b-button v-else variant="primary" @click="login">Sign In</b-button>    
      </div>
    </template>
    <script>
    import { mapGetters, mapActions } from 'vuex';
    import { auth, provider } from '../firebase'
    
    export default {
      name: 'Login',
      data() {
        return {
          imageSrc: ''
        };
      },
      computed: mapGetters(['user']),
      methods: {
        ...mapActions(['signIn', 'signOut']),
        login() {
          auth
          .signInWithPopup(provider)
          .then(authUser => {
            this.imageSrc = authUser.user.photoURL;
            this.signIn(authUser);
          })
          .catch(error => alert(error.message))      
        },
        logout() {
          this.signOut();
        }
      }
    }
    </script>
    <style>
    .login {
      text-align: center;
    }
    
    .logout {
      cursor: pointer;
    }
    </style>
    

    NewTodo 구성 요소 생성


    component 폴더 아래에 새 파일을 만듭니다. NewTodo.vue다음 스크립트를 이 파일로 복사합니다
    <template>
      <b-form @submit="AddNewTodo">
        <b-form-group
          label="Add new todo"
          label-for="newTodo"
        >
          <b-form-input
            id="newTodo"
            placeholder="What needs to be done"
            v-model="todo"
            required
          >        
          </b-form-input>
        </b-form-group>
        <b-button type="submit" variant="primary">Add New Todo</b-button>
      </b-form>
    </template>
    <script>
    // import actions
    import { mapGetters, mapActions } from 'vuex'
    
    export default {
      name: "NewTodo",
      data() {
        return {
          // data for binding to the input text
          todo: ''
        }
      },
      computed: mapGetters(['user']),
      methods: {
        ...mapActions(['addTodo']),
        /**
         * Form submit hanlder
         */
        AddNewTodo (event) {
          event.preventDefault();
          if (this.todo && this.todo !== "") {
            // update data base
            this.addTodo({
              user: this.user.user,
              title: this.todo
            })                  
            // clear todo
            this.todo = "";
          }      
        }
      }
    }
    </script>
    <style>
    
    </style>
    

    TodoItem 구성 요소 생성


    component 폴더 아래에 새 파일을 만듭니다. TodoItem.vue다음 스크립트를 복사합니다.TodoItem 모회사TodoList로부터 부동산 3곳 취득
  • id-항목 식별자(이 값은firestore 데이터베이스에서 생성됨)
  • 머리글 - 항목 설명을 나타내는 문자열
  • 완료 - 프로젝트의 완료 여부를 나타내는 부울 값입니다.
  • <template>
      <b-form>
        <b-row>
          <b-col cols="11">
            <b-form-checkbox switch size="lg" :checked="completed" 
                @change="toggleComplete">                    
              <label :class="{complete: completed}">{{title}}</label>      
            </b-form-checkbox>       
          </b-col>      
          <b-col cols="1">
            <b-icon icon="trash" class="hover-trash" @click="removeTodo"></b-icon>
          </b-col>
        </b-row>
    
      </b-form>
    </template>
    <script>
    import { mapGetters, mapActions } from 'vuex'
    
    export default {
      name: 'TodoItem',
      props: {
        id: String, // The todo item key
        title: String, // The title description of the todo item
        completed: Boolean // indicating if the todo item has been completed
      },
      computed: mapGetters(['user']),
      methods: {
        ...mapActions(['toggleCompleted', 'deleteTodo']),
        toggleComplete () {
          // change the status of the todo item
          this.toggleCompleted({
            user: this.user.user,
            id: this.id,
            completed: !this.completed
          })
        },
        removeTodo () {
          // delete the todo from the state collection
          this.deleteTodo({
            user: this.user.user,
            id: this.id
          });
        }
      }
    }
    </script>
    <style scoped>
    .complete {
      text-decoration: line-through;
    }
    
    .hover-trash:hover {
      color: red;
    }
    
    .row {
      border-bottom: 1px solid gray;
    }
    </style>
    

    NewTodo 구성 요소 생성


    component 폴더 아래에 새 파일을 만듭니다. TodoList.vue다음 스크립트를 이 파일로 복사합니다
    <template>
      <b-container fluid class="ml-3">
        <h1>Todo list goes here</h1>
        <ul>
          <li v-for="todo in allTodos" :key="todo.id">
            <todo-item :title="todo.title" :completed="todo.completed" :id="todo.id" ></todo-item>        
          </li>
        </ul>
      </b-container>
    </template>
    <script>
    import TodoItem from './TodoItem.vue'
    // vuex actions and getters
    import { mapGetters, mapActions } from 'vuex';
    
    export default {
      name: 'TodoList',
      components: {
        TodoItem
      },
      computed: mapGetters(['allTodos', 'user']),
      methods: {
        ...mapActions(['fetchTodos'])
      },
      created() {
        this.fetchTodos(this.user.user);
      }
    }
    </script>
    <style scoped>
    ul li {
      list-style: none;
    }
    </style>
    

    응용 프로그램 구성 요소에 구성 요소 추가

    App.vue를 열고 코드를 다음과 같이 업데이트합니다.
    <template>
      <div class="mt-5">
        <img alt="Vue logo" src="./assets/logo.png"> 
          <login></login>
          <div v-if="user">
            <b-container>        
              <new-todo></new-todo>      
            </b-container>
            <todo-list></todo-list>   
          </div>
      </div>
    </template>
    
    <script>
    import NewTodo from './components/NewTodo.vue'
    import TodoList from './components/TodoList.vue'
    import { mapGetters } from 'vuex'
    import Login from './components/Login.vue'
    
    export default {
      name: 'App',
      computed: mapGetters(['user']),
      components: {
        NewTodo,
        TodoList,      
        Login
      }
    }
    </script>
    
    <style>
    * {
      margin: 0;
      padding: 0;
    }
    
    img {
      display: block;
      margin-left: auto;
      margin-right: auto;
    }
    </style>
    

    구축 및 배포


    현재 우리는 모든 구성 요소를 완성했고 로컬에서 응용 프로그램을 테스트했다.지금은 응용 프로그램을 구축하고 배치할 때이다.

    애플리케이션 구축


    npm run build
    
    이 명령은 프로그램을 컴파일하고 폴더 dist 에 필요한 모든 파일을 생성합니다.구글 클라우드에 배치될 폴더다.

    배치하다


    전 세계에 설치되어 있는지 확인하십시오firebase-tools.
    npm install -g firebase-tools
    
    지금 당신은 로그인해야 합니다
    firebase login
    
    Firebase 프로젝트 시작
    firebase init
    
    관리형 옵션을 선택합니다.
    필요public directorydist를 입력합니다.
    한 페이지의 프로그램을 사용해야 할 때 "y"를 입력하십시오
    GitHub 자동화 빌드를 요청할 때 N를 입력합니다.
    덮어쓰기N가 필요한 경우 index.html를 입력합니다.우리는 우리의 서류를 보존하고 싶다
    그리고 위탁 관리 항목을 선택하십시오. 새 항목을 만들거나 만들었으면 기존 항목을 선택할 수 있습니다.
    배포 프로젝트
    firebase deploy
    
    축하합니다!!!todo 프로그램의 구축을 처음부터 끝까지 완료했고, 이 프로그램을 성공적으로 배치했습니다.

    좋은 웹페이지 즐겨찾기