基础案例:TodoMVC


    需求说明


    开始


    1. <template v-if="todos.length > 0">
    2. <section class="main">
    3. <input
    4. id="toggle-all"
    5. class="toggle-all"
    6. type="checkbox"
    7. v-bind:checked="getToggleAllStatus()"
    8. @change="handleToggleAll">
    9. <label for="toggle-all">Mark all as complete</label>
    10. <ul class="todo-list">
    11. <!-- These are here just to show the structure of the list items -->
    12. <!-- List items should get the class `editing` when editing and `completed` when marked as completed -->
    13. <li
    14. v-for="(item, index) in todos"
    15. v-bind:class="{completed: item.done}">
    16. <div class="view">
    17. <input class="toggle" type="checkbox" v-model="item.done">
    18. <label>{{ item.title }}</label>
    19. <button @click="handleRemoveTodo(index)" class="destroy"></button>
    20. </div>
    21. <input class="edit" value="Rule the web">
    22. </li>
    23. </ul>
    24. </section>
    25. <!-- This footer should hidden by default and shown when there are todos -->
    26. <footer class="footer">
    27. <!-- This should be `0 items left` by default -->
    28. <span class="todo-count"><strong>0</strong> item left</span>
    29. <!-- Remove this if you don't implement routing -->
    30. <ul class="filters">
    31. <li>
    32. <a class="selected" href="#/">All</a>
    33. </li>
    34. <li>
    35. <a href="#/active">Active</a>
    36. </li>
    37. <li>
    38. <a href="#/completed">Completed</a>
    39. </li>
    40. </ul>
    41. <!-- Hidden if no completed items are left ↓ -->
    42. <button class="clear-completed">Clear completed</button>
    43. </footer>
    44. </template>
    45. ...

    添加任务

    1. ...
    2. class="new-todo"
    3. placeholder="What needs to be done?"
    4. v-on:keyup.enter="handleAddTodo">
    5. ...
    1. ...
    2. methods: {
    3. ...
    4. handleAddTodo (e) {
    5. const {target} = e // target 就是触发该事件的 DOM
    6. const {value} = target
    7. const {todos} = this
    8. // 拿到数组最后一个元素的 id + 1 就可以得到一个唯一不重复的 id
    9. // 当数组是空的时候根本就没有最后一项,所以 todos[todos.length - 1] 的结果就是 undefined
    10. // undefined.id 不就报错了吗?
    11. const lastTodo = todos[todos.length - 1]
    12. // 如果有最后一个元素,则让该元素.id + 1,否则默认给个 1
    13. const id = lastTodo ? lastTodo.id + 1 : 1
    14. if (value.trim().length !== 0) {
    15. this.todos.push({
    16. id, // 当 key 和 value 名字一样的时候,可以简写, id 等价于 id: id
    17. title: value,
    18. done: false
    19. })
    20. // 操作 DOM 清空文本框
    21. target.value = ''
    22. }
    23. },
    24. ...
    25. }
    26. ...

    切换所有任务的完成状态

    1. ...
    2. <input
    3. id="toggle-all"
    4. class="toggle-all"
    5. type="checkbox"
    6. v-bind:checked="getToggleAllStatus()"
    7. @change="handleToggleAll">
    8. ...
    1. ...
    2. <button @click="handleRemoveTodo(index)" class="destroy"></button>
    3. ...
    1. ...
    2. methods: {
    3. ...
    4. handleRemoveTodo (delIndex) {
    5. this.todos.splice(delIndex, 1)
    6. },
    7. ...
    8. }
    9. ...

    删除所有已完成任务

    1. ...
    2. <button
    3. class="clear-completed"
    4. @click="handleClearAllDone">Clear completed</button>
    5. ...
    1. ...
    2. methods: {
    3. ...
    4. handleClearAllDone () {
    5. for (let i = 0; i < this.todos.length; i++) {
    6. if (item.done === true) {
    7. this.todos.splice(i, 1)
    8. i-- // 在遍历过程中删除元素之后,让索引减一次,防止有漏网之鱼
    9. }
    10. }
    11. ...
    12. }
    13. ...

    显示所有剩余未完成任务数

    1. ...
    2. methods: {
    3. ...
    4. getRemaining () {
    5. let count = 0
    6. this.todos.forEach(item => {
    7. if (item.done === false) {
    8. count++
    9. }
    10. })
    11. return count
    12. }
    13. ...
    14. }
    15. ...
    1. ...
    2. <strong>{{ remaining }}</strong> item left</span>
    3. ...
    1. ...
    2. computed: {
    3. ...
    4. remaining () {
    5. let count = 0
    6. this.todos.forEach(item => {
    7. if (item.done === false) {
    8. count++
    9. }
    10. })
    11. return count
    12. }
    13. ...
    14. }
    15. ...
    1. ...
    2. new Vue({
    3. ...
    4. data: {
    5. ...
    6. todos: JSON.parse(window.localStorage.getItem('todos') || '[]')
    7. ...
    8. },
    9. ...
    10. watch: {
    11. ...
    12. todos: {
    13. handler () { // 固定的 handler ,当 todos 发生改变会自动调用 handler 方法
    14. // 本地存储只能存储字符串,所以这里要把数组转成字符串再存储
    15. window.localStorage.setItem('todos', JSON.stringify(this.todos))
    16. },
    17. deep: true // deep 配置为 true 表示深度监视
    18. }
    19. ...
    20. },
    21. ...
    22. })