Espero que la pregunta tenga algún sentido. Estoy usando Vue JS y tengo pocos elementos en bucle usando v-for. Dentro de cada bloque de elementos que se enlazan, hay un botón junto con un div. En este caso, mi ciclo se ejecuta tres veces. Eso significa que obtengo tres botones en cada bloque de código en bucle, junto con esos tres div.
Cuando hago clic en uno de los tres botones, me gustaría que el div en ese bloque reciba una clase dinámicamente. Sin embargo, tal como está, cuando hago clic en uno de los tres botones, la clase se agrega, pero se agrega a los tres elementos div en bucle dentro del bucle.
¿Cómo puedo hacer que el div en bucle actual solo reciba la clase específica cuando se hace clic en el botón relacionado, sin que los otros dos div del bucle también lo reciban?
Aquí está mi código hasta ahora con lo que he probado yo mismo:
<template> <div v-for="(todo, index) in todos" :key="index" class="relative"> <button @click="showDiv"> show div </button> <div :class="appear" class="absolute bg-red-500"> <p>{{ todo.text }}</p> </div> </div> </template> <script> import {defineComponent} from 'vue' export default defineComponent({ data() { return { appear: 'left-0', todos: [ { text: 'Learn Laravel' }, { text: 'Learn Vue JS' }, { text: 'Learn Tailwind CSS' }, ] } }, methods: { showDiv() { this.appear = 'left-2/4'; } } }) </script>Esto sucede porque tiene todo su código ejecutándose en el mismo "nivel" (o alcance para ser más técnico), por lo tanto, el DOM "piensa" que se supone que todos los elementos deben agregarse la clase. Puede resolver este problema fácilmente simplemente creando un nuevo componente para fragmentos de código repetitivos (como cuando necesita un bucle for) y haciendo uso de las ranuras de Vue ( https://vuejs.org/v2/guide/components-slots. html ) característica.
// corresponding example JS file or section (depending on your setup) for TodoListItem export default { name: 'TodoListItem', props: { todo: { type: Object, requried: true } }, data() { return { isClicked: false } }, methods: { toggleIsClicked() { this.isClicked = !this.isClicked; }, }, }; <!-- index.html --> <todo-list> <todo-list-item v-for="(todo, index) in todos" :key="index" :todo="todo" ></todo-list-item> </todo-list> <!-- TodoList.vue --> <template> <div class="todo-container"> <slot></slot> </div> </template> <!-- TodoListItem.vue --> <!-- Don't forget to set your props in the corresponding component JS file or else your TodoListItem.vue won't know about the todo object you are passing down to it. --> <!-- You will also need to move your @click handler here too in the methods section --> <template> <div class="relative"> <button @click="showDiv">show div</button> <div :class="appear" class="absolute bg-red-500"> <p>{{ todo.text }}</p> </div> </div> </template>Espero que esto ayude a mi amigo!
La razón es que está utilizando una variable que appear para administrar el estado de todos los botones, en su lugar, puede mantener booleanos separados llamados visible para cada uno de los elementos.
Compruebe el siguiente ejemplo de trabajo
var app = new Vue({ el: "#app", data() { return { appear: 'left-0', /*** Change added to below array ***/ todos: [ { text: 'Learn Laravel', visible: false }, { text: 'Learn Vue JS', visible: false }, { text: 'Learn Tailwind CSS', visible: false }, ] } }, /** Changes added below **/ computed: { getButtonText() { return ind => { return this.todos[ind].visible ? 'hide div': 'show div'; } }, getClass() { return ind => { return this.todos[ind].visible ? 'left-2/4': 'absolute bg-red-500'; } } }, methods: { showDiv(index) { this.todos[index].visible = !this.todos[index].visible; // Change added } } }) <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <div v-for="(todo, index) in todos" :key="index" class="relative"> <button @click="showDiv(index)"> {{getButtonText(index)}} <!-- Change added --> </button> <div :class="getClass(index)"> <!-- Change added --> <p>{{ todo.text }}</p> </div> </div> </div>agregue un campo booleano en su matriz y use ese campo como condición para la clase dinámica, por ejemplo
{ text: 'Learn Laravel', isLeft: false }, { text: 'Learn Vue JS', isLeft: false }, { text: 'Learn Tailwind CSS', isLeft: false },Ahora, al hacer clic, simplemente cambie el campo isLeft y utilícelo como condición para la clase dinámica
<div v-for="(todo, index) in todos" :key="index" class="relative"> <button @click="todo.isLeft = !todo.isLeft"> show div </button> <div :class="{'left-2/4': todo.isLeft}" class="absolute bg-red-500"> <p>{{ todo.text }}</p> </div> </div>