카테고리 없음

[Vue] Vue-with-vuex

황성안 2021. 5. 13. 23:15
728x90
반응형

0513

cd todo-with-vuex 해서 설치하기..

vue create todo-with-vuex
vue add vuex
npm run serve

Helloworld 관련 삭제

 

UI

  • All:

    • Complted : count
    • Inprogress: count
  • TodoList

  • TodoForm

  • TodoList

vues.js 에 가보시면 이름을 만드는 방법도 나와있다.


오늘 우리는 아래와 같은 컴포넌트를 만들어준다.

  • components

    • TodoForm
    • TodoList
    • TodoListItem

 

  1. TodoForm

    <template>
      <div>
          <input type="text" @keyup.enter="onEnter">
          <button @click="onClick">Add</button>
      </div>
    </template>
    
    <script>
    export default {
        name: 'TodoForm',
        methods: {
            onEnter() {
                console.log('oke')
            },
            onClick() {
                console.log('okc')
            },
        }
    }
    </script>
    
    <style>
    
    </style>
    

     

 

  1. App.vue

 

부트스트랩사용하기

  • 부트스트랩 접속(https://getbootstrap.com/)

  • publick 폴더안의 index.html의 head안에 넣어줍니다.

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-wEmeIV1mKuiNpC+IOBjI7aAzPcEZeedi5yW5f2yOq55WWLwNGmvvx4Um1vskeMj0" crossorigin="anonymous">
    

     

 

store의 index.js 로

state 밑에 getters 만들어주고 todoList 정의하고 이를 컨트롤 하려면

mutations 에 업데이트 함수를 만들어준다

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
      todoList: [],
  },
  getters: {
  },
  mutations: {
    CREATE_TODO(state, newTodo) {
      state.todoList.push(newTodo)
    },
  },
  actions: {
  },
  modules: {
  }
})

그러면 Create_TODO를 TODOform 에서 가져다 사용할수있따

this.$store.commit('CREATE_TODO', this.userInput) 추가해주기

data를 사용하여 양방향 바인딩해주기 v-model

<template>
  <div>
      <input 
      type="text" 
      v-model="userInput"
      @keyup.enter="onEnter">
      <button @click="onClick">Add</button>
  </div>
</template>

<script>
export default {
    name: 'TodoForm',
    data() {
        return {
            userInput: '',
        }
    },
    methods: {
        onEnter() {
            //console.log('oke')
            this.$store.commit('CREATE_TODO',this.userInput)
        },
        onClick() {
            // console.log('okc')
            this.$store.commit('CREATE_TODO',this.userInput)
        },
    }
}
</script>

<style>

</style>

가공을 해서 넘겨줘보자

            const newTodo = {
                id: '',
                content: '',
                completed: false,
            }

서버에서 가져오면 PK값이있다.

content는 this.userInput으로 넣어주자.

 

 

 

 

UUID 사용해보자(유효id: 지문)

참고 : https://github.com/VitorLuizC/vue-uuid

 

npm i vue-uuid

설치가 완료됐다면 main.js에 등록해주자.

import Vue from 'vue'
import App from './App.vue'
import store from './store'
import UUID from 'vue-uuid'


Vue.use(UUID)// 등록
Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App)
}).$mount('#app')

그리고 버전마다 다른 uuid를 적용시켜주자(홈페이지 맨아래 v1~v5 참고)

TodoForm 으로가자 id에 this.$uuid.v1(),를 추가시켜주고

아래 this.$store.commit('CREATE_TODO',this.newTodo) 로 넘겨준다.

<template>
  <div>
      <input 
      type="text" 
      v-model="userInput"
      @keyup.enter="onEnter">
      <button @click="onClick">Add</button>
  </div>
</template>

<script>
export default {
    name: 'TodoForm',
    data() {
        return {
            userInput: '',
        }
    },
    methods: {
        onEnter() {
            //console.log('oke')
            const newTodo = {
                id: this.$uuid.v1(),
                content: this.userInput,
                completed: false,
            }

            this.$store.commit('CREATE_TODO',newTodo)
        },
        onClick() {
            // console.log('okc')           
            const newTodo = {
                id: this.$uuid.v1(),
                content: this.userInput,
                completed: false,
            }

            this.$store.commit('CREATE_TODO',newTodo)
        },
    }
}
</script>

<style>

</style>

 

그리고 TodoForm 에서 newTodo 함수를 만들어주자.

<template>
  <div>
      <input 
      type="text" 
      v-model="userInput"
      @keyup.enter="onEnter"
      >
      <button @click="onClick">Add</button>
  </div>
</template>

<script>
export default {
    name: 'TodoForm',
    data() {
        return {
            userInput: '',
        }
    },
    methods: {
        onEnter() {
            //console.log('oke')
            const newTodo = {
                id: this.$uuid.v1(),
                content: this.userInput,
                completed: false,
            }

            this.$store.commit('CREATE_TODO',newTodo)
        },
        onClick() {
            // console.log('okc')           
            const newTodo = {
                id: this.$uuid.v1(),
                content: this.userInput,
                completed: false,
            }

            this.$store.commit('CREATE_TODO',newTodo)
        },
        newTodo(content) {
            return {
                id: this.$uuid.v1(),
                content,
                completed: false,
            }
        },
    }
}
</script>

<style>

</style>

이렇게 되면 onclick과 onEnter의 newTodo를 삭제하고 옆으로 넘길수있다.

const 를 삭제하고 this.$store.commit('CREATE_TODO', this.newTodo(this.userInput) ) 를 적어준다.

<template>
  <div>
      <input 
      type="text" 
      v-model="userInput"
      @keyup.enter="onEnter"
      >
      <button @click="onClick">Add</button>
  </div>
</template>

<script>
export default {
    name: 'TodoForm',
    data() {
        return {
            userInput: '',
        }
    },
    methods: {
        
        onEnter() {
            //console.log('oke')
            this.$store.commit('CREATE_TODO', newTodo(this.userInput) )
        },
        onClick() {
            // console.log('okc')           
            this.$store.commit('CREATE_TODO', this.newTodo(this.userInput) )
        },
        newTodo(content) {
            return {
                id: this.$uuid.v1(),
                content,
                completed: false,
            }
        },
    }
}
</script>

<style>

</style>

그리고 어차피 함수가 겹치니 하나로 통일시켜주자 onSumbit

<template>
  <div>
      <input 
      type="text" 
      v-model="userInput"
      @keyup.enter="onSubmit"
      >
      <button @click="onSubmit">Add</button>
  </div>
</template>

<script>
export default {
    name: 'TodoForm',
    data() {
        return {
            userInput: '',
        }
    },
    methods: {
        onSubmit() {
            this.$store.commit('CREATE_TODO', this.newTodo(this.userInput) )
        },
        newTodo(content) {
            return {
                id: this.$uuid.v1(),
                content,
                completed: false,
            }
        },
    }
}
</script>

<style>

</style>

 

 

index.js의 getters 로가자

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    todoList: [],
  },
  getters: {
    getTodoList(state) {
      return state.todoList
    },
  },
  mutations: {
    CREATE_TODO(state, newTodo) {
      state.todoList.push(newTodo)
    },
  },
  actions: {
  },
  modules: {
  }
})

다음 TodoList.vue로가자

  • 반복문 돌리면서 출력해주기
<template>
  <div>
      <div 
      v-for="todo in todoList"
      :key="todo.id"
      >
        {{ todo.content }}
      </div>
  </div>
</template>

<script>
export default {
    name: 'TodoList',
    computed: {
        todoList() {
            return this.$store.getters.getTodoList
        },
    },
}
</script>

<style>

</style>

app.vue

<template>
  <div id="app">
    <TodoForm/>
    <TodoList/>
  </div>
</template>

<script>
import TodoForm from '@/components/TodoForm'
import TodoList from '@/components/TodoList'

export default {
  name: 'App',
  components: {
    TodoForm,
    TodoList,
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

 

 

 

 

 

TodoListItem.vue로 이동해주자

객체 형태로 적어주고

명시적으로 적어주기

<template>
  <div>
      <input type="checkbox" v-model="todo.completed">
      <span>{{ todo.content }}</span>
  </div>
</template>

<script>
export default {
    name: 'TodoListItem',
    props: {
        todo: {
            type: Object,
            required: true,
        },
    },
}
</script>

<style>

</style>

TodoList에서 불러와주자

<template>
  <div>
    <TodoListItem
     v-for="todo in todoList"
     :key="todo.id"
     :todo="todo"
    />
  </div>
</template>

<script>
import TodoListItem from '@/components/TodoListItem'

export default {
    name: 'TodoList',
    components: {
        TodoListItem,
    },
    computed: {
        todoList() {
            return this.$store.getters.getTodoList
        },
    },
}
</script>

<style>

</style>

 

 

 

 

클릭했을때 완료 표시

  • 체크박스에 체크를하면 완료가되게!

  • 2가지 방법이있다. TodoList 의 div에서 하는방법

    • @click.native 를 사용해야한다
  • TodoListItem에서 하는방법 컴포넌트에서하기

    • div @click="onClick"
    • 아래 methods 를 만들어서 추가하자
  • index.js 의 create_todo 아래에 update_todo를 만들어주자

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    todoList: [],
  },
  getters: {
    getTodoList(state) {
      return state.todoList
    },
  },
  mutations: {
    CREATE_TODO(state, newTodo) {
      state.todoList.push(newTodo)
    },
    UPDATE_TODO(state, targetTodo) {
      // todoList에서 targetTodo를 찾고
      // targetTodo의 complted 값을 변경
    state.todo = state.todoList.map((todo)=> {
        if (todo.id == targetTodo.id) {
          // 참이면 거짓으로, 거짓이면 참으로 변경
          todo.completed = !todo.completed
        }
        return todo
      })

    },
  },
  actions: {
  },
  modules: {
  }
})

TodoListItem

  • props에서 data로 넘긴다.
  • this.$store.commit('UPDATE_TODO', this.todo) 값확인 잘되는지 확인은 홈페이지에서 add 해보고 개발자 옵션 vue에서 competed에서 체크후 참으로바뀌면 잘동작
<template>
  <div @click="onClick">
      <input type="checkbox" v-model="todo.completed">
      <span :class="{ completed: todo.completed }">{{ todo.content }}</span>
  </div>
</template>

<script>
export default {
    name: 'TodoListItem',
    props: {
        todo: {
            type: Object,
            required: true,
        },
    },
    methods: {
        onClick() {
            // 1. mutation 호출
            this.$store.commit('UPDATE_TODO', this.todo)
            // 2. store에서 todo의 completed 값 변경
        },
    },
}
</script>

<style>

</style>

 

 

 

삭제 로직 만들기

Todo listitem 에 버튼을 만든다.

  • @click="deleteClick"
  • methods 에 delete click 함수만들고
  • this.$stroe.commit('DELETE_TODO', this.Todo)

mutations 안에 delete_todo(대문자)

state, targetTodo
cosnt targetTodoIdx = state.todoList.indexOf(targetTodo)
state.todoList.splice(targetTodoIdx, 1)

 

 

 

 

클릭해서 삭제되면 삭제 라고 띄우기

TodoListItem


 

 

 

 

 

배포하기

새로운 폴더로 node module 뺴고 옮긴다음

git bash

ls

git init

git add .

git commit -m " 이름"

까지만해주고 git hub 르가서 rep 만든다

 

 

 

빈칸 입력안되게하기

TodoForm

Dom 조작을 강제할때

querySelector을 vue 한테 좋은방향으로 쓰는것

ref="todoInput" input 에 추가해주자.

onSubmit에

this.$refs.todoInput 인풋 셀럭터를 찍어서 온다음

<template>
  <div>
      <div class="d-flex">
          <input 
            type="text" 
            ref="todoInput"
            autofocus
            @input="onUserInput"
            @keyup.enter="onSubmit"
            class="form-control"
            >
            <button 
            @click="onSubmit"
            class="btn btn-primary btn-custom-sm"
            >
            Add
            </button>
        </div>
        <div> {{ userInput.length }}/ 50자</div>
  </div>
</template>

<script>
export default {
    name: 'TodoForm',
    data() {
        return {
            userInput: '',
        }
    },
    methods: {
        onUserInput(e) {
            if (e.target.value.length > 50){
                e.target.value = this.userInput
                return
            }
            this.userInput = e.target.value
        },
        onSubmit() {
            // 검증( 글자수 100자 제한 )
            if (this.userInput.length > 50) {
                const errorMsg = '검색어는 50자 이하로 작성해주세요.'
                this.$store.commit('UPDATE_ERROR', errorMsg)

                this.userInput=''
                return
            }
            this.$store.commit('UPDATE_ERROR', '')
            this.$store.commit('CREATE_TODO', this.newTodo(this.userInput) )
            //검색창 검색후 초기화
            this.userInput=''
            this.$refs.todoInput.value=''
        },
        newTodo(content) {
            return {
                id: this.$uuid.v1(),
                content,
                completed: false,
            }
        },
    }
}
</script>

<style>
.btn-custom-sm {
    width: 100px !important;
    height: 36px !important;
    font-size: 75%
}
</style>

 

728x90
반응형