我正在try 制作一个使用VueJS(2.x)的纯客户端Todolist.以下是我的HTML:

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>To-do List</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
    </head>
    <body>
        
        <div id="app">
            <h1>To-do List</h1>
            <h2>Completed Tasks!</h2>
            <ul>
                <li v-for="item in complete">{{ item.description }}<input type="checkbox" :checked="item.done" @change="item.done = false"></li>
            </ul>
            <h2>Uncompleted Tasks!</h2>
            <ul>
                <li v-for="item in uncomplete">{{ item.description }}<input type="checkbox" :checked="item.done" @change="item.done = true"></li>
            </ul>
        </div>
        
        <script src="https://cdn.jsdelivr.net/npm/vue@2.7.13/dist/vue.js"></script>
        <script type="module" src="scripts/app.js"></script>
    </body>
    </html>

然后在脚本/app.js中,我执行了以下操作:

    'use strict'
    
    let app = new Vue({
    
        el      : "#app",
        data    : {
            tasks: [
                { description: 'Say Hello', done: true },
                { description: 'Review Code', done: false },
                { description: 'Read Emails', done: false },
                { description: 'Reply to Emails', done: false },
                { description: 'Wash The Dishes', done: true },
                { description: 'Stop Working', done: true },
            ]
        },
        computed : {
            complete : function() {
                return this.tasks.filter(task => task.done === true);
            },
            uncomplete : function() {
                return this.tasks.filter(task => task.done === false);
            }
        }
    
    });

我的问题很简单:当我更改给定列表中复选框的状态(选中或取消选中)时,紧随其后的复选框也会切换状态.

我不明白为什么会发生这种情况,也不知道如何修复它.如果一个人能告诉我why这种情况会发生(这样每当我有一个行为不端的v-for/switch 状态时,我就不必回到这里),以及如何修复它,那就太好了!

推荐答案

  1. 首先.data中最好使用Function,而不是Object,否则可能会导致更新错误.

因为Function只有在组件定义中使用时才被接受.

// wrong
data: {
    tasks: []
}

// correct
data() {
    return {
        task: []
    }
}
  1. 您不能直接更改computed属性,因为默认情况下只有Computed Getter.如果要处理computed属性,请给它Computed Setter分.
// wrong
computed: {
    complete(){
      return this.tasks.filter(task => task.done === true);
    },
}

// right
computed: {
    complete: {
        get() {
            return this.tasks.filter(task => task.done === true);
        },
        set(value) {
            this.task.forEach((task, index) => {
                let matched = value.find(({ description }) => description === task.description);
                if(matched) {
                    this.task[index] = matched;
                }
            });
        }
    }
}
  1. 您不能通过v-for绑定值,因为vue2无法识别数组中的更改.
<!-- wrong -->
<li
  v-for="item in complete">
  {{ item.description }}
  <input
    type="checkbox"
    :checked="item.done"
    @change="item.done = false">
</li>

<!-- correct -->
<li
  v-for="(item, index) in complete">
  {{ item.description }}
  <input
    type="checkbox"
    :checked="item.done"
    @change="complete[index].done = false">
</li>

new Vue({
  el: "#app",
  data() {
    return {
      tasks: [
        { description: 'Say Hello', done: true },
        { description: 'Review Code', done: false },
        { description: 'Read Emails', done: false },
        { description: 'Reply to Emails', done: false },
        { description: 'Wash The Dishes', done: true },
        { description: 'Stop Working', done: true },
      ]
    };
  },
  computed : {
    complete: {
      get() {
        return this.tasks.filter(task => task.done === true);
      },
      set(value) {
        this.task.forEach((task, index) => {
          let matched = value.find(({ description }) => description === task.description);
          if(matched) {
              this.task[index] = matched;
          }
        });
      }
    },
    uncomplete: {
      get() {
        return this.tasks.filter(task => task.done === false);
      },
      set(value) {
        this.task.forEach((task, index) => {
          let matched = value.find(({ description }) => description === task.description);
          if(matched) {
              this.task[index] = matched;
          }
        });
      }
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <h1>To-do List</h1>
  <h2>Completed Tasks!</h2>
  <ul>
    <li
      v-for="(item, index) in complete">
      {{ item.description }}
      <input
        type="checkbox"
        v-model="complete[index].done">
    </li>
  </ul>
  <h2>Uncompleted Tasks!</h2>
  <ul>
    <li
      v-for="(item, index) in uncomplete">
      {{ item.description }}
      <input
        type="checkbox"
        v-model="uncomplete[index].done">
    </li>
  </ul>
</div>

Vue.js相关问答推荐

如何默认打开一个v-list-group?

在 onMounted 之前渲染的 Vue 模板

v-slot: activator 中 {attrs} 参数的作用是什么?

我可以从手表调用方法并安装吗?

在没有组件的vue js中拖放

Vuetify 在数据表中插入操作按钮并获取行数据

eslint – 如何知道 defined定义规则的位置

如何在 vuejs 中异步加载图像 src url?

Vue&TypeScript:在项目目录外的 TypeScript 组件中实现导入时如何避免错误 TS2345?

SassError:媒体查询表达式必须以(开头

如何在某些路由上隐藏全局组件(例如导航栏)?

Laravel 事件未广播

Laravel 中的 VueJS 组件实现中的鼠标悬停

Vue router路由,Root Vue 没有数据?

使用 vue-router 的默认子路由

Vuex 存储数据总是驻留在内存中?

axios 拦截器响应未定义

根据nuxt中的url参数动态加载组件

在 vue js 中的何处以及如何存储 API 端点?

在 Vuejs 中全局导入 Axios 方法