Skip to content

Instantly share code, notes, and snippets.

@duncan60
Created January 18, 2018 06:11
Show Gist options
  • Save duncan60/f38e83eb14fe4b3a2f369048fc625012 to your computer and use it in GitHub Desktop.
Save duncan60/f38e83eb14fe4b3a2f369048fc625012 to your computer and use it in GitHub Desktop.
Vue Todo with Vuex
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="//cdn.jsdelivr.net/npm/vue"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/vuex/3.0.1/vuex.min.js"></script>
</head>
<body>
<h1>Vue Todo with Vuex</h1>
<div id="app" >
<div>
<p>Need Todo</p>
<ul>
<todo-item
v-for="(item, key) in unCompleteTodos"
:todo="item"
:key="key"
:edit="onEdit"
:save="onSave"
:complete="onComplete">
</todo-item>
<li>
<input
placeholder="Enter text"
v-model="newTodo"
v-on:keyup.stop="updateField('newTodo', $event.target.value)"
>
<button @click="onAddTodo" :disabled="isDisabled">
add new todo
</button>
</li>
</ul>
</div>
<div>
<p>Complete Todo</>
<ul>
<todo-item
v-for="(item, index) in completeTodos"
:todo="item"
:key="item.id"
:restore="onRestore">
</todo-item>
</ul>
</div>
</div>
</body>
</html>
// vuex store
const ADD_NEW_TODO = 'ADD_NEW_TODO';
const UPDATE_TODO = 'UPDATE_TODO';
const UPDATE_FIELD = 'UPDATE_FIELD';
const store = new Vuex.Store({
state: {
newTodo: '',
todos: {
1:{ id:1, text: '學習 JavaScript', isEdit: false, isComplete: false },
2:{ id:2, text: '學習 Vue', isEdit: false, isComplete: false },
3:{ id:3, text: '學習 React', isEdit: false, isComplete: true }
}
},
getters: {
getTodos: state => isComplete => {
list = {}
for (let [k, v] of Object.entries(state.todos)) {
if(v.isComplete === isComplete) {
list[k] = v;
}
}
return list;
}
},
mutations: {
[ADD_NEW_TODO]: (state, payload) => {
newId = parseInt(1000*Math.random());
new_todo = {
id: newId,
text: state.newTodo,
isEdit: false,
isComplete: false
}
state.todos = {
...state.todos,
[newId]: new_todo,
};
state.newTodo = '';
},
[UPDATE_TODO]: (state, payload) => {
state.todos[payload.id] = {
...payload,
};
},
[UPDATE_FIELD]: (state, payload) => {
state[payload.field] = payload.value;
}
},
actions: {
addNewTodo: ({ commit }) => {
commit(ADD_NEW_TODO);
},
updateTodo: ({ commit }, todo) => {
commit(UPDATE_TODO, todo);
},
updateField: ({ commit }, fieldObj) => {
commit(UPDATE_FIELD, fieldObj);
}
}
})
// vue component
Vue.component('todo-item', {
props:['todo', 'edit', 'save', 'complete', 'restore'],
data() {
return {
text: this.todo.text,
}
},
methods: {
onHandler(type) {
this[type](this.todo, this.text);
}
},
template: `
<li v-if="!todo.isEdit && !todo.isComplete">
<span>
{{ text }}
</span>
<button @click="onHandler('complete')">
complete
</button>
<button @click="onHandler('edit')">
edit
</button>
</li>
<li v-else-if="todo.isComplete">
<span>
{{ todo.text }}
</span>
<button @click="onHandler('restore')">
restore
</button>
</li>
<li v-else>
<input type="text" v-model="text">
<button @click="onHandler('save')">
save
</button>
</li>
`
})
const app = new Vue({
el: '#app',
store,
computed: {
unCompleteTodos() {
return this.$store.getters.getTodos(false);
},
completeTodos() {
return this.$store.getters.getTodos(true);
},
newTodo() {
return this.$store.state.newTodo;
},
isDisabled() {
return this.$store.state.newTodo !== '' ? false : true;
}
},
methods: {
updateTodos(todo) {
this.$store.dispatch('updateTodo', todo);
},
updateField(field, value) {
this.$store.dispatch('updateField', {field, value});
},
onAddTodo() {
this.$store.dispatch('addNewTodo');
},
onEdit(todo) {
this.updateTodos({
...todo,
isEdit: true,
});
},
onSave(todo, newText) {
this.updateTodos({
...todo,
text: newText,
isEdit: false,
});
},
onComplete(todo) {
this.updateTodos({
...todo,
isComplete: true
});
},
onRestore(todo) {
this.updateTodos({
...todo,
isComplete: false
});
}
}
})
@duncan60
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment