2017-05-04 6 views
0

Ich arbeite an einer grundlegenden Aufgabenanwendung. Jede Aufgaben-/Aufgabenaufgabe wird als Eingabeelement in einer Vue-Komponente aufgelistet, und die <list-item> werden mit einem v-Symbol angezeigt, das auf ein Aufgaben-Array zeigt.Aktualisieren des gebundenen Werts eines Eingangs bei der Bearbeitung

Ich versuche, den Benutzer zu ermöglichen, jede Aufgabe Eingabe zu bearbeiten, und bei Änderung des Werts, aktualisieren Sie die Array-Element (und nicht nur die Eingabe selbst). Mein @change-Ereignis auf dem Eingang wird ausgelöst, aber ich weiß nicht, was ich nach diesem Punkt tun soll.

https://jsfiddle.net/xbxm7hph/

HTML:

<div class="app"> 

    <div class="add-control-area columns is-mobile is-multiline"> 

     <responsive-container> 

      <div class="field is-grouped"> 
       <div class="control is-expanded"> 
        <input class="input add-control-text" type="text" placeholder="New Task" v-model="newTask" v-on:keyup.enter="addTask"> 
       </div> 
       <div class="control"> 
        <a class="button is-white add-control-button" @click="addTask" :disabled="!isThereText">Add Task</a> 
       </div> 
      </div> 

     </responsive-container> 

     <responsive-container> 

      <list-item v-for="task, index in tasks" :item="task" :index="index" @task-completed="completeTask(index)" @task-deleted="deleteTask(index)" ></list-item> 

     </responsive-container> 

    </div> 

</div> 

JS:

Vue.component('list-item', { 
    props: ['item', 'index'], 
    template: `<div class="task-wrapper"> 

<input class="task" :value="item" @change="updateTask()"> 

    <div class="task-control delete-task" @click="deleteTask()"></div> 
    <div class="task-control complete-task" @click="completeTask()"></div> 

</div> 
    `, 
    methods: { 
    completeTask: function() { 
     this.$emit('task-completed', this.index); 
    }, 
    deleteTask: function() { 
     this.$emit('task-deleted', this.index); 
    }, 
    updateTask: function() { 
     console.log('changed'); 
    } 
    } 
}); 

Vue.component('responsive-container', { 
    template: ` 
    <div class="column is-4-desktop is-offset-4-desktop is-10-tablet is-offset-1-tablet is-10-mobile is-offset-1-mobile"> 
      <div class="columns is-mobile"> 
       <div class="column is-12"> 
        <slot></slot> 
       </div> 
      </div> 
    </div> 
    ` 
}); 

var app = new Vue({ 
    el: '.app', 
    data: { 
     tasks: [], 
    completedTasks: [], 
    newTask: '' 
    }, 
    methods: { 
    addTask: function() { 
     if(this.isThereText) { 
     this.tasks.push(this.newTask); 
     this.newTask = ''; 
     this.updateStorage(); 
     } 
    }, 
    completeTask: function(index) { 
     this.completedTasks.push(this.tasks[index]); 
     this.tasks.splice(index, 1); 
     this.updateStorage(); 
    }, 
    deleteTask: function(index) { 
     this.tasks.splice(index, 1); 
     this.updateStorage(); 
    }, 
    updateStorage: function() { 
     localStorage.setItem("tasks", JSON.stringify(this.tasks)); 
    } 
    }, 
    computed: { 
    isThereText: function() { 
     return this.newTask.trim().length; 
    } 
    }, 

    // If there's already tasks stored in localStorage, 
    // populate the tasks array 
    mounted: function() { 
    if (localStorage.getItem("tasks")) { 
     this.tasks = JSON.parse(localStorage.getItem("tasks"));  
    } 
    } 
}); 

Antwort

1

ein v-model directive auf <list-item> Komponente verwenden, statt in einer item Eigenschaft übergeben. Sie werden auch von der Anordnung in einer Referenz zu übergeben müssen (tasks[index]), weil task in diesem Rahmen eine Kopie, die nicht an das Element des Arrays gebunden ist:

<list-item v-for="task, index in tasks" v-model="tasks[index]"></list-item> 

In Ihrer Komponentendefinition für das Listenelement Sie müssen jetzt eine value Prop aufnehmen (dies wird bei der Verwendung von v-model übergeben) und setzen Sie eine Dateneigenschaft item auf diesen Wert. Dann gibt ein input Ereignis auf der Änderung den item Wert zu übergeben (das ist, was die Komponente für hört bei der Verwendung von v-model):

Vue.component('list-item', { 
    props: ['value'], 
    template: `<div class="task-wrapper"> 
    <input class="task" v-model="item" @change="updateTask"></div> 
    </div> 
    `, 
    data() { 
    return { 
     item: this.value, 
    } 
    }, 
    methods: { 
    updateTask: function() { 
     this.$emit('input', this.item); 
    } 
    } 
}); 

Here's a fiddle with those changes.


  • Als Bert Evans erwähnte Obwohl dies funktioniert, erfordert Vue, dass Komponenten, die die v-for-Anweisung verwenden, auch ein key-Attribut verwenden (andernfalls erhalten Sie eine Warnung von Vue):

    <list-item 
        v-for="task, index in tasks" 
        :key="index" 
        v-model="tasks[index]" 
    ></list-item> 
    
  • auch erkennen, dass die index Variable in einem v-for Umfang ändern kann, was bedeutet, dass das Element mit dem Index 1 könnte 4 Index ändern und dies einige Probleme mit sich bringen kann als die Anwendung komplexer wird. Ein besserer Weg wäre, items als Objekt mit einer id Eigenschaft zu speichern. Auf diese Weise können Sie eine unveränderliche ID mit dem Objekt verknüpfen.

+0

'key' ist für benutzerdefinierte Komponenten erforderlich. Die Klammern für die Methodenhandler sind überflüssig. Außerdem binden Sie direkt an "Wert", der eine Eigenschaft ändert. https://vuejs.org/v2/guide/list.html#Components-and-v-for – Bert

+0

@BerTevans warum nicht 'index' verwenden? Und ich weiß, dass die Dokumentation sagt, Schlüssel ist erforderlich, aber ist das nicht nur, wenn Sie möchten, dass die Daten binden?Ich denke, 'v-model' umgeht das. Ich bekomme die erwarteten Ergebnisse und keine Fehler oder Warnungen in der Geige. – thanksd

+0

Sie erhalten keine Warnungen, weil er die Produktionsversion von Vue verwendet. Wir bekommen immer wieder Fragen von Leuten, die 'index' als Variable zu ihren Komponenten benutzen. Das Problem ist 'Index' Änderungen und' ID's nicht. – Bert

0

Sie können den Index und neuen Wert auf Ihre Änderungsereignishandler übergeben:

<input class="task" :value="item" @change="updateTask(index, $event)"> 

Dann Zugang th em entsprechend:

updateTask: function(index, event) { 
    console.log(index);   
    console.log(event.target.value); 
} 
Verwandte Themen