2017-05-04 5 views
0

私は基本的なToDoアプリケーションで作業しています。各作業項目/タスク項目は、Vue <list-item>コンポーネントの入力項目としてリストされ、<list-item>には、タスク配列を指すvが表示されます。編集時に入力のバウンド値を更新する

私は各タスクの入力を編集できるようにしようとしていますが、値を変更すると、(入力自体ではなく)配列項目が更新されます。入力上の@changeイベントが発生していますが、私はこの時点以降に何をすべきかについて迷っています。

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

答えて

1

ではなくitemプロパティに渡すのでは、あなたの<list-item>コンポーネントにv-model directiveを使用してください。この範囲内taskは、配列の要素にバインドされていないコピーであるので、あなたはまた、配列(tasks[index])から参照を渡す必要があります。

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

リスト項目のコンポーネント定義でvalue小道具(これはv-modelを使用したときに渡されるものです)を取り込み、その値にデータプロパティーを設定する必要があります。次いで、item値を渡す変化inputイベントを放出する(これは、コンポーネントが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.


  • バートエバンスが述べたようにこれが機能していても、v-forディレクティブを使用しているコンポーネントでもkeyという属性を使用する必要があります(そうしないとVueから警告が表示されます)。

    <list-item 
        v-for="task, index in tasks" 
        :key="index" 
        v-model="tasks[index]" 
    ></list-item> 
    
  • また、v-for範囲内index変数はインデックス1の項目はインデックス4に変更される可能性があり、アプリケーションがより複雑になるにつれて、これはいくつかの問題を提起することができることを意味、変更することができることを実現します。より良い方法は、idプロパティを持つオブジェクトとしてitemsを格納することです。この方法では、アイテムに関連付けられた不変のIDを持つことができます。

+0

カスタムコンポーネントには 'key'が必要です。メソッドハンドラのかっこは余分です。また、プロパティを変更している 'value'に直接バインドしています。 https://vuejs.org/v2/guide/list.html#Components-and-v-for – Bert

+0

@BertEvansなぜ 'index'を使わないのですか?ドキュメントには 'key'が必要だと書かれていますが、データをバインドしたいだけではありません。私は 'vモデル 'がそれを回避すると思う。私は予想される結果を得て、エラーや警告はフィドルでは得られません。 – thanksd

+0

Vueのプロダクションバージョンを使用しているため警告が表示されません。私たちは、 'index'をコンポーネントの変数として使用している人々から質問を得ています。問題は 'index'の変更であり、' id'の変更はありません。 – Bert

0

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

次にアクセスth EMは、それに応じて:

updateTask: function(index, event) { 
    console.log(index);   
    console.log(event.target.value); 
} 
関連する問題