Vuex ToDoList sample

Vuex 및 bootstrap 을 활용한 할 일 목록 예제입니다

by plpot

HTML

<script src="https://unpkg.com/vuex/dist/vuex.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>

<!-- Add this to <head> -->
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.css" />

<!-- Add this after vue.js -->
<script src="//unpkg.com/babel-polyfill@latest/dist/polyfill.min.js"></script>
<script src="//unpkg.com/bootstrap-vue@latest/dist/bootstrap-vue.js"></script>


<div id="app">
  <todo-main></todo-main>
  <div>
    <todo-list></todo-list>
  </div>
</div>

<template id="main">
  <div class="border-bottom pt-4 pb-4">
    <b-container>
      <b-row class="text-center" align-v="center">
        <b-col cols="2">할 일 : </b-col>
        <b-col cols="8">
          <b-form-input size="sm" v-model.trim="todoText" autofocus v-on:keyup.native.enter="saveTodo"></b-form-input>
        </b-col>
        <b-col cols="2">
          <b-button v-bind:disabled="disabled" variant="success" size="sm" @click="saveTodo">추가</b-button>
        </b-col>
      </b-row>
    </b-container>
  </div>
</template>

<template id="todolist">
  <div>
    <b-container class="mt-3">
      <b-form-radio-group v-model="condition">
        <b-row>
          <b-col>
            <b-form-radio value="all">전체 할 일</b-form-radio>
          </b-col>
          <b-col>
            <b-form-radio value="todo">남은 할 일</b-form-radio>
          </b-col>
          <b-col>
            <b-form-radio value="done">끝난 할 일</b-form-radio>
          </b-col>
        </b-row>
      </b-form-radio-group>
    </b-container>
    
    <b-list-group class="mt-3 ml-2 mr-2" v-if="todos.length === 0">
      <b-list-group-item variant="secondary" class="mt-1">
        <b-row class="text-center" align-v="center">
          <b-col>
            <span class="text-dark">할 일이 없습니다.</span>
          </b-col>
        </b-row>
     ...

Vue

const TodoMain = {
  template: '#main',
  data: function() {
    return {
    	todoText: ''
    }
  },
  methods: {
  	saveTodo: function(){
    	if(this.todoText != '')
      	this.$store.dispatch('saveTodo', this.todoText)
      this.todoText = ''
    }
  },
  computed: {
  	disabled () {
    	return this.todoText.trim().length === 0
  	}
  }
}

const TodoList = {
  template: '#todolist',
  data: function() {
    return {
    	condition: 'all',
      selected: 0
    }
  },
  methods: {
  	toggleTodo: function(id){
    	this.$store.dispatch('toggleTodo', id)
    },
  	deleteConfirm: function(id){
    	this.selected = id
      this.$refs.delConfirm.show()
    },
  	deleteTodo: function(){
    	if(this.selected > 0){
      	this.$store.commit('deleteTodo', this.selected)
      }
      this.selected = 0
    },
    textClass: function(todo) {
    	return {
      	'text-dark': todo.done === false,
        'text-danger': todo.done === true
      }
    }
  },
  computed: {
  	todos () {
    	switch(this.condition){
      	case 'todo':
        	return this.$store.state.todos.filter(todo => todo.done === false)
        case 'done':
        	return this.$store.state.todos.filter(todo => todo.done === true)
      }
      return this.$store.state.todos
  	}
  }
}

const store = new Vuex.Store({
  state: {
  	id: 1,
    todos: []
  },
  mutations: {
  	increment (state){
    	state.id++
    },
  	deleteTodo (state, id) {
    	state.todos = state.todos.filter(todo => todo.id !== id)
    }
  },
  actions: {
  	saveTodo (context, message) {
    	context.state.todos.push({
      	id: context.state.id,
      	text: message,
      	done: false
    	})
      context.commit('increment')
    },
  	toggleTodo (context, id) {
    	let todo = context.getters.getTodo(id)
      todo.done = !todo.done
    }
  },
  getters: {
    getTodo: (state) => (id) => {
    	return state.todos.find(todo => todo.id === id)
  	}
  }
})

const app = new Vue({
  el: '#app',
  store,
  components:...