Inverta boolean no clique com v-for?

votos
2

Iniciante a JS e VueCLI então eu vou tentar explicar da melhor forma que posso. Estou usando Express meu back-end.

Estou tentando mudar o boolean na minha matriz de objetos no clique. Eu sou capaz de conseguir isso, mas quando eu clico em um item da lista diferente no meu loop v-por isso está lançando o boolean em todos os outros índices de minha matriz. Aqui está o meu código:

Express: / rotas:

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

Aplicativo web:

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

e agora meu componente 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>

Então, quando eu clico no meu primeiro item da lista muda a tarefa: t1 a verdade, mas se eu clicar no segundo item da lista muda t1 volta para Falso e t2 para True. Eu não sei exatamente o que estou fazendo de errado. Eu nem tenho certeza que esta é a melhor maneira de fazer isso. A minha questão principal é que eu não sei por que isso está acontecendo.

Qualquer ajuda é muito apreciada!

Publicado 19/09/2018 em 13:24
fonte usuário
Em outras línguas...                            


3 respostas

votos
2

Você é provavelmente o excesso de complicar isso.

Tudo o que você precisa é

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

Demo ~ https://jsfiddle.net/xy1q0auL/2/

Não há (óbvio) necessidade de re-fetch as tarefas cada vez que você clicar em um. É por isso que as alterações anteriores são repostas; é porque você sobrescrever todos os dados com os valores não modificados de getTasks().

Respondeu 19/09/2018 em 13:30
fonte usuário

votos
0

Você pode fazer seu simplesmente:

 <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>

Ans para o método

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

        }
    }
Respondeu 19/09/2018 em 13:48
fonte usuário

votos
0

Quando completeMovie () é chamado, você envia uma solicitação HTTP para o servidor que vai enviar-lhe lista de tarefas de volta inalterado. Eu não entender claramente o que é que você está tentando alcançar, mas o retorno de chamada na promessa não tem sens. No retorno você reafecte a lista de "tarefas" na sua vue:

digite descrição da imagem aqui

Neste caso, aqui é o cronograma de eventos que você tem que fazer:

  • Quando a página cliente é carregado, Vue inicializado, o componente vue chama seu webservice para obter a lista de tarefas, em seguida, imprimi-lo.
  • Então, quando eu clicar em uma tarefa, você tem que fazer uma chamada de outro HTTP para o seu webservice (em outra rota), que irá atualizar a lista de tarefas e devolvê-lo.
  • Em seguida, na chamada do seu componente vue você reafecte a nova lista de tarefas.
Respondeu 19/09/2018 em 13:36
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more