2017-05-04 34 views
0

我正在研究基本的待办事宜应用程序。每个待办事项/任务项目在Vue <list-item>组件中被列为输入项目,而<list-item>则显示为v-for指向任务数组。编辑时更新输入的绑定值

我试图让用户编辑每个任务输入,并在更改值时,有此更新数组项(而不仅仅是输入本身)。输入的我的@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

<list-item>组件使用v-model directive,强似在item财产。您还需要从阵列(tasks[index])的引用来传递,因为task在此范围内是不绑定到数组的元素的副本:

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

在你的组件定义列表项,你需要现在接受value道具(这是使用v-model时得到的结果)并将数据属性item设置为该值。然后,在变化发出input事件传递item值(这是该组件正在侦听使用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.


  • 如伯特埃文斯提到,尽管这可行,但Vue要求使用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和应用变得越来越复杂这可能会带来一些问题。更好的方法是将items作为id属性的对象存储。这样你可以有一个不可变的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'作为其组件变量的人的问题。问题是'索引'变化和'ID's不。 – Bert

0

您可以将指数和新的价值传递给您的更改事件处理程序:

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

然后访问日EM因此:

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