Skip to content

Instantly share code, notes, and snippets.

@azyobuzin
Last active February 15, 2020 15:16
Show Gist options
  • Save azyobuzin/6aa890009ed5fcb29760cfa9da4910e2 to your computer and use it in GitHub Desktop.
Save azyobuzin/6aa890009ed5fcb29760cfa9da4910e2 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TODO になる予定</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app">Loading</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.js"></script>
<script src="https://unpkg.com/vuex@3.1.2/dist/vuex.js"></script>
<script src="main.js"></script>
</body>
</html>
// <store>
Vue.use(Vuex)
const ADD_TODO_ITEM = 'addTodoItem'
const SET_DONE = 'setDone'
const store = new Vuex.Store({
state: {
todos: [],
},
mutations: {
[ADD_TODO_ITEM](state, payload) {
let item = {
id: state.todos.length,
text: payload.text,
important: payload.important || false,
done: payload.done || false }
state.todos.push(item)
},
[SET_DONE](state, { id, value }) {
state.todos[id].done = value
}
},
})
const STORAGE_KEY = 'todos'
// localStorage からデータを復元
const initialTodos = localStorage.getItem(STORAGE_KEY)
if (initialTodos) {
JSON.parse(initialTodos).forEach(x => store.commit(ADD_TODO_ITEM, x))
}
// store に変更があったら、 localStorage に保存
store.subscribe((_mutation, state) => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(state.todos))
})
// </store>
// <components>
const TodoItemComponent = {
name: 'TodoItem',
props: {
item: {
type: Object,
required: true,
},
},
computed: {
textStyle() {
if (this.item.important) {
return { backgroundColor: '#FFAAFF' }
} else {
return { }
}
},
done: {
get() {
return this.item.done
},
set(value) {
this.$store.commit(SET_DONE,
{ id: this.item.id, value })
}
},
},
template: `
<transition name="todo-item-transition" appear>
<li v-if="!done">
<input type="checkbox" v-model="done" />
<span :style="textStyle">{{ item.text }}</span>
</li>
</transition>
`
}
const TodoListComponent = {
name: 'TodoList',
components: { 'todo-item': TodoItemComponent },
computed: Vuex.mapState(['todos']),
template: `
<ul>
<todo-item v-for="item in todos" :key="item.id" :item="item" />
</ul>
`
}
const TodoInputComponent = {
name: 'TodoInput',
data() {
return {
text: '',
important: false,
}
},
computed: {
cannotSubmit() {
return !(this.text && this.text.length > 0)
}
},
methods: {
onSubmit() {
this.$store.commit(ADD_TODO_ITEM,
{ text: this.text, important: this.important })
this.text = ''
this.$refs.textbox.focus()
}
},
template: `
<form action="#" @submit.prevent="onSubmit">
<input ref="textbox" type="text" v-model="text" />
<button :disabled="cannotSubmit">追加</button>
<br />
<label>
<input type="checkbox" v-model="important" />
重要
</label>
</form>
`
}
// </components>
new Vue({
el: "#app",
store,
components: {
'todo-list': TodoListComponent,
'todo-input': TodoInputComponent,
},
template: `
<div>
<todo-list />
<todo-input />
</div>
`
})
.todo-item-transition-enter, .todo-item-transition-leave-to {
opacity: 0;
margin-left: 50px;
}
.todo-item-transition-enter-active, .todo-item-transition-leave-active {
transition: all .3s ease;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment