【问题标题】:Updating an input's bound value when edited编辑时更新输入的绑定值
【发布时间】:2017-05-04 19:24:42
【问题描述】:

我正在开发一个基本的待办事项应用程序。每个待办事项/任务项在 Vue <list-item> 组件中作为输入项列出,<list-item>s 显示为带有指向任务数组的 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"));    
    }
  }
});

【问题讨论】:

    标签: javascript vue.js vuejs2


    【解决方案1】:

    在您的&lt;list-item&gt; 组件上使用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.


    • 正如 Bert Evans 所提到的,即使这样可行,Vue 要求使用 v-for 指令的组件也使用 key 属性(否则你会收到来自 Vue 的警告):

      <list-item
        v-for="task, index in tasks" 
        :key="index"
        v-model="tasks[index]"
      ></list-item>
      
    • 1234563更好的方法是将items 存储为具有id 属性的对象。这样,您就可以拥有与项目关联的不可变 id。

    【讨论】:

    • key 是自定义组件所必需的。方法处理程序上的括号是多余的。此外,您还直接绑定到正在修改属性的valuevuejs.org/v2/guide/list.html#Components-and-v-for
    • @BertEvans 为什么不使用index?而且我知道文档说key 是必需的,但这不只是为了让数据绑定吗?我认为v-model 规避了这一点。我得到了预期的结果,小提琴中没有错误或警告。
    • 您不会收到警告,因为他使用的是 Vue 的生产版本。我们不断收到人们使用index 作为组件变量的问题。问题是 index 发生变化而 ids 没有变化。
    • @BertEvans 好的电话。我将更新我的答案以包含 PSA
    • @BertEvans,等待您的第一条评论已更改?
    【解决方案2】:

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

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

    然后相应地访问它们:

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

    【讨论】:

      猜你喜欢
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-28
      • 2014-12-18
      • 2011-12-22
      相关资源
      最近更新 更多