Атрибут VueJS — Checkbox «checked» не соответствует его состоянию

#javascript #vue.js #checkbox

#javascript #vue.js #флажок

Вопрос:

Это простой пример списка задач, в котором я бы хотел, чтобы флажки были установлены или нет, в зависимости от того, выполняется задача или нет.

После снятия флажка в разделе «Завершить задачи» следующий флажок будет отображаться непроверенным, даже если он все еще установлен в разделе «Все задачи».

Чтобы легко воспроизвести, снимите флажок «Перейти в хранилище» в разделе «Завершить задачи». «Чистая комната» не будет отмечена, даже если она по-прежнему отмечена в разделе «Все задачи» и все еще завершена в данных.

Как я могу это исправить?

 <html>
<head>
    <title>VueJS</title>
</head>
<body>
<div id="root">
    <h1>All tasks</h1>

    <ul>
        <li v-for="task in tasks">
            {{ task.description }}
            <input type="checkbox" v-model="task.completed" :id="task.id">
        </li>
    </ul>

    <h1>Complete tasks</h1>

    <ul>
        <li v-for="completeTask in completeTasks">
            {{ completeTask.description }}
            <input type="checkbox" v-model="completeTask.completed" :id="completeTask.id">
        </li>
    </ul>

    <h1>Incomplete tasks</h1>

    <ul>
        <li v-for="incompleteTask in incompleteTasks">
            {{ incompleteTask.description }}
            <input type="checkbox" v-model="incompleteTask.completed" :id="incompleteTask.id">
        </li>
    </ul>
</div>

<script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script>

<script>
  new Vue({
    el: '#root',
    data: {
      tasks: [
        {id: 1, description: 'Go to the store', completed: true},

        {id: 2, description: 'Finish X', completed: false},

        {id: 3, description: 'Do Y', completed: false},

        {id: 4, description: 'Clear inbox', completed: false},

        {id: 5, description: 'Make Z', completed: false},

        {id: 6, description: 'Clean room', completed: true},
      ],
    },

    computed: {
      completeTasks() {
        return this.tasks.filter(task => task.completed);
      },

      incompleteTasks() {
        return this.tasks.filter(task => !task.completed);
      },
    },
  });
</script>
</body>
</html>  

Ответ №1:

Проблема в том, что Vue пытается быть умным и «повторно использовать» DOM. Но в этом случае это сработает против вас.

Чтобы исправить это, вам нужно добавить key к каждому элементу с помощью v-for , таким образом, Vue может отслеживать, какой <li> есть какой, на основе ключа.

Это более подробно объясняется в документах:https://v2.vuejs.org/v2/guide/list.html#Maintaining-State

 <html>
<head>
    <title>VueJS</title>
</head>
<body>
<div id="root">
    <h1>All tasks</h1>

    <ul>
        <li v-for="task in tasks" :key="task.id">
            {{ task.description }}
            <input type="checkbox" v-model="task.completed" :id="task.id">
        </li>
    </ul>

    <h1>Complete tasks</h1>

    <ul>
        <li v-for="completeTask in completeTasks" :key="completeTask.id">
            {{ completeTask.description }}
            <input type="checkbox" v-model="completeTask.completed" :id="completeTask.id">
        </li>
    </ul>

    <h1>Incomplete tasks</h1>

    <ul>
        <li v-for="incompleteTask in incompleteTasks" :key="incompleteTask.id">
            {{ incompleteTask.description }}
            <input type="checkbox" v-model="incompleteTask.completed" :id="incompleteTask.id">
        </li>
    </ul>
</div>

<script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script>

<script>
  new Vue({
    el: '#root',
    data: {
      tasks: [
        {id: 1, description: 'Go to the store', completed: true},

        {id: 2, description: 'Finish X', completed: false},

        {id: 3, description: 'Do Y', completed: false},

        {id: 4, description: 'Clear inbox', completed: false},

        {id: 5, description: 'Make Z', completed: false},

        {id: 6, description: 'Clean room', completed: true},
      ],
    },

    computed: {
      completeTasks() {
        return this.tasks.filter(task => task.completed);
      },

      incompleteTasks() {
        return this.tasks.filter(task => !task.completed);
      },
    },
  });
</script>
</body>
</html>