How can I make a list containing checkboxes attached to an object in a state that a v-for directive toggles (without toggling other checkboxes in the list)?
P粉738346380
P粉738346380 2024-03-29 22:31:39
0
1
364

I'm trying to make a client-side to-do list using VueJS (2.x). This is my 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>

Then in scripts/app.js I did this:

    '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);
            }
        }
    
    });

My problem is simple: when I change the state of a checkbox in a given list (check or uncheck it), the checkbox immediately following it also switches state.

I don't understand why this happens and how to fix it. If anyone could tell me why this is happening (so that I don't have to come back here when v-for/switch-state misbehaves) and how to fix it, that would be great!

P粉738346380
P粉738346380

reply all(1)
P粉312195700
  1. first. It is best to use Function instead of Object in data, otherwise it may cause update errors.

Because Function is only accepted when used in a component definition.

// wrong
data: {
    tasks: []
}

// correct
data() {
    return {
        task: []
    }
}
  1. You cannot directly change the compulated property, which has only one Compulated Getter by default. If you want to handle a compated property, give a computed setter to it.
// 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. Cannot bind values ​​via v-for because vue2 does not recognize changes in the array.

  • {{ item.description }}
  • {{ item.description }}

  • 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;
              }
            });
          }
        }
      }
    });
    sssccc
    

    To-do List

    Completed Tasks!

    • {{ item.description }}

    Uncompleted Tasks!

    • {{ item.description }}
    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template