Инвертировать логическое значение при клике с помощью v-for? - PullRequest
0 голосов
/ 19 сентября 2018

Новичок в JS и VueCLI, поэтому я постараюсь объяснить как можно лучше.Я использую Express в качестве моего бэк-энда.

Я пытаюсь изменить логическое значение в моем массиве объектов при нажатии.Я могу сделать это, но когда я нажимаю на другой элемент списка в моем цикле v-for, это переворачивает логическое значение во всех других индексах моего массива.Вот мой код:

Экспресс: / маршруты:

        // fake data store
        const tasks = [
           { id: 1, task: 't1', completed: false},
           { id: 2, task: 't2', completed: false},
           { id: 3, task: 't3', completed: false}
        ];

        /**
        * GET handler for /tasks route
        * @returns {Array.<{id: Number, task: String, completed: Boolean}>} array of task objects 
        */
        router.get('/', (req, res) => {
           res.send(tasks);
        });

Веб-приложение:

        /**
        * GET /tasks
        * @returns Promise => {Array.<{id: Number, task: String, completed: Boolean}>} array of task objects
        */
        export function getTasks() {
           return request('tasks');
        }

и теперь мой компонент Vue:

        <template>
        <div id="tasks">
            <h2>Movies to Add</h2>
            <ul class="todo-list">
            <li v-for='task in tasks' :id="task.id" v-on:click="completeMovie($event)" :key='task.id' class="todo-list__li">
                <input class="todo-list__input" type="checkbox" :name='task.task' :id="task.task">
                <div class="todo-list__checkbox">
                <span class="todo-list__checkbox-inner"><i></i></span>
                </div>
                <label :for='task.task'>{{ task.task }}</label>
            </li>
            </ul>
        </div>
        </template>

        <script>
        import {getTasks} from './../../services/tasks';

        export default {
        name: 'TaskList',
        data: function() {
            return {
            tasks: []
            };
        },
        created: function() {
            getTasks()
            .then(res => this.tasks = res);
        },
        methods: {
            completeMovie: function (event) {
            var taskId = event.currentTarget.id -1;

            getTasks()
                .then((res) => {
                this.tasks = res;
                res[taskId].completed = !res[taskId].completed;
                });
            }
        }
        }
        </script>

Поэтому, когда я нажимаю на свой первый элемент списка, он изменяет Задачу: t1 на True, но если я щелкаю на втором элементе списка, он снова меняет t1 на False и t2 на True.Я не уверен, что именно я делаю неправильно.Я даже не уверен, что это лучший способ сделать это.Моя главная проблема - я не уверен, почему это происходит.

Любая помощь очень ценится!

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Когда вызывается completeMovie (), вы отправляете HTTP-запрос на ваш сервер, который отправит вам обратно неизмененный список задач.Я не совсем понимаю, чего вы пытаетесь достичь, но ваш обратный вызов в обещании не имеет смысла.В обратном вызове вы снова воздействуете на список «задач» в вашем vue:

enter image description here

В этом случае, вот временная шкала события, которую вы должны сделать:

  • Когда страница клиента загружена, Vue Initialized, компонент vue вызывает ваш веб-сервис, чтобы получить список задач, а затем распечатать его.
  • Затем, когда я нажимаю на задачу, вы должны сделатьеще один HTTP-вызов к вашему веб-сервису (по другому маршруту), который обновит список задач и вернет его.
  • Затем при вызове компонента vue вы снова воздействуете на новый список задач.
0 голосов
/ 19 сентября 2018

Вы можете сделать это просто:

 <li v-for='task in tasks' :id="task.id" v-on:click="completeMovie(task.id)" :key='task.id' class="todo-list__li">
            <input class="todo-list__input" type="checkbox" :name='task.task' :id="task.task">
            <div class="todo-list__checkbox">
            <span class="todo-list__checkbox-inner"><i></i></span>
            </div>
            <label :for='task.task'>{{ task.task }}</label>
        </li>

Ответ для метода

completeMovie: function ($taskId) {
        this.tasks[$taskId].completed = !this.tasks[$taskId].completed;

        }
    }
0 голосов
/ 19 сентября 2018

Вы, вероятно, слишком усложняете это.

Все, что вам нужно, это

<li v-for="task in tasks" :key="task.id" 
    @click="task.completed = !task.completed" 
    class="todo-list__li">

Демо-версия * https://jsfiddle.net/xy1q0auL/2/

Нет (очевидной) необходимости повторно-приобретать задачи каждый раз, когда вы нажимаете на одну.Вот почему ваши предыдущие изменения сбрасываются;это потому, что вы перезаписываете все данные неизмененными значениями из getTasks().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...