TodoItem.vue 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. <template>
  2. <li class="todo" :class="{ completed: todo.done, editing }">
  3. <div class="view">
  4. <input class="toggle"
  5. type="checkbox"
  6. :checked="todo.done"
  7. @change="toggleTodo(todo)">
  8. <label v-text="todo.text" @dblclick="editing = true"></label>
  9. <button class="destroy" @click="removeTodo(todo)"></button>
  10. </div>
  11. <input class="edit"
  12. v-show="editing"
  13. :value="todo.text"
  14. ref="input"
  15. @keyup.enter="doneEdit"
  16. @keyup.esc="cancelEdit"
  17. @blur="doneEdit">
  18. </li>
  19. </template>
  20. <script>
  21. import { ref, watch, nextTick } from 'vue'
  22. import { useStore } from 'vuex'
  23. export default {
  24. name: 'Todo',
  25. props: ['todo'],
  26. setup (props) {
  27. const input = ref(null)
  28. const editing = ref(false)
  29. watch(editing, (v) => {
  30. v && nextTick(() => { input.value.focus() })
  31. })
  32. const store = useStore()
  33. const editTodo = (todo, value) => store.dispatch('editTodo', { todo, value })
  34. const toggleTodo = (todo) => store.dispatch('toggleTodo', todo)
  35. const removeTodo = (todo) => store.dispatch('removeTodo', todo)
  36. function doneEdit (e) {
  37. const value = e.target.value.trim()
  38. if (!value) {
  39. removeTodo(props.todo)
  40. } else if (editing.value) {
  41. editTodo(props.todo, value)
  42. }
  43. editing.value = false
  44. }
  45. function cancelEdit (e) {
  46. e.target.value = props.todo.text
  47. editing.value = false
  48. }
  49. return {
  50. input,
  51. editing,
  52. toggleTodo,
  53. doneEdit,
  54. cancelEdit,
  55. removeTodo
  56. }
  57. }
  58. }
  59. </script>