VueJs:如何编辑数组项

5

一个简单的Todo-App。对于我提出这样一个基本的问题,请原谅我的无知。

但是,您如何编辑数组中的某个项目呢?

通常,我会尝试将输入框的值绑定到数据对象上的新属性,并通过Vue的双向数据绑定在单击时将此新属性分配给旧属性。

像这样:http://jsfiddle.net/z7960up7/

但在我的情况下,我使用了v-repeat指令,它循环遍历我的数据数组,但如果我使用v-model指令来使用双向数据绑定,则属性的值会被破坏。 (请参见此处:http://jsfiddle.net/doL46etq/2/

现在我想知道,如何更新我的任务数组:

我的想法是,在单击时通过方法传递VueObject(this),然后在我的事件处理程序中定义索引,然后使用索引更新任务数组,如下所示:

HTML:

<input v-el="editInputField" type="text" value="{{ task.body }}" v-on="keyup: doneEdit(this) | key 'enter'"/>

<button v-on="click: editTask(this)">
     Edit
</button>

JS:

methods: {
    editTask: function (task) {
        var taskIndex = this.tasks.indexOf(task.task);

        this.tasks[taskIndex] = {
            'body': document.querySelector('input').value,
            'completed': false
        };

        console.log(task.task.body);
    },
}

这是一个关于此的示例:

http://jsfiddle.net/doL46etq/3/

但数据对象根本没有更新,我想知道如何更新它。使用Vue编辑数组元素的最佳方法是什么?编辑:一种简单的方法是删除元素,并使用push方法将新元素添加到数组中,但我真的想只更新元素,因为我希望将数据对象与后端保持同步。
2个回答

3
简短回答:在扩展构造函数中使用组件,然后将索引作为属性传递到该组件中,并使用计算属性来往返链接到您的数据。
但不要只满足于简短的回答。这里是详细的解释:
情况:我正在使用您的JSFiddle作为此答案的基础。
在HTML中,您有:
<td>{{ task.body }}</td>
                <td>
                    <div>
                        <input v-el="editInputField" type="text" value="{{ task.body }}" v-on="keyup: doneEdit(this) | key 'enter'" v-model="newEdit"/>
                    </div>
                </td>
                <td>
                    <button v-on="click: editTask(this)" class="mdl-button mdl-js-button mdl-button--icon"> <i class="material-icons">create</i>

                    </button>
                </td>

我们希望使用组件替换这段代码。使用该组件可以帮助我们在数据集中确定正在操作的索引/行。
<td v-component="listitem" index="{{$index}}"></td>

下一步:定义组件。
为了不在实例中混淆组件,我们将为vue对象创建一个单独的构造函数,以便将新元素分配给我们的新对象。
这是通过extend完成的。
window.newVue =  Vue.extend({
components:
{
    'listitem': {

        props: ['index'],

        computed: {
        // both get and set
        body: {
          get: function () {

            return this.$parent.tasks[this.index].body;
          },
          set: function (v) {
            this.$parent.tasks[this.index].body = v
          }
        }
      },
        template: '<td>{{ body }}</td><td><div><input type="text" v-model="body" value="{{ body }}"/></div></td><td></td>',
    }
}

});

由于我们无法使用extend来正确定义数据,因此在编写组件时假定数据已经存在。

步骤3:定义实际数据: 我们将不再使用Vue作为对象构造函数,而是使用我们新创建的实例化器。

new newVue({
el: '#todoapp',

data: {
    tasks: [{
        'body': 'Eat breakfast',
        'completed': false
    }, {
        'body': 'Drink milk',
        'completed': false
    }, {
        'body': 'Go to the store',
        'completed': false
    }],

    newTask: '',
},

});

就是这样了!

如果您无法跟随发生的情况:这里有Fiddle!

附注:有关此代码工作方式的更多信息,请访问vuejs.org。


谢谢Sangun。虽然我还没有深入研究过Vue组件,所以需要一些时间来理解你的答案。但是我想知道,在这里是如何进行编辑/更新的,是否可以解释一下,因为我猜测并没有使用组件:https://github.com/tastejs/todomvc/blob/gh-pages/examples/vue/js/app.js - LoveAndHappiness
此外,在您的jsfiddle中何时触发Ajax请求? - LoveAndHappiness
1
这取决于您想要使用Ajax请求做什么。如果您希望更新数据库中的信息,则从组件的Setter触发会是最好的选择(但请记住,每当单个字符更改时都会发出请求,因此您可能需要延迟并缓冲所有更改!)如果您希望更新数据,我建议添加一个新属性而不是定义数据。这将允许您通过属性编辑值。这意味着,如果您使用v-repeat item,则可以使用{{item.property}}来更新变量。 - Sangun
谢谢Sangun,我已经接受了你的回答。不过,我可能会重新提出这个问题,请求一个没有“组件”的解决方案,因为我(可能是错误的)认为,组件是为了帮助完成基本任务变得更容易,而不是使基本任务成为可能。我将会仔细研究todomvc.com应用程序和你的解决方案,并在那之后可能会更明智。非常感谢。 - LoveAndHappiness
1
你可以使用Vue.JS的同一位开发者制作的路由器插件来完成相同的操作,而无需使用组件。然而,我对这个插件并不熟悉,无法给出令人满意的答案。如果你希望有一个不需要组件的解决方案(在我看来同样有效),你可以尝试使用https://github.com/vuejs/vue-router。希望能帮到你! - Sangun

2

实际上,更新数组项的最简单方法是使用v-model指令与任务正文进行双向绑定。

例如:

http://jsfiddle.net/z7960up7/2/

<div id="demo">
    {{ message }}

    <div class="edit">
        <input type="text" v-model="message">         
        <button v-on="click: editMessage">Edit</button>
    </div>        
    <pre>{{ $data | json }}</pre>
</div>

当你在输入框内失去焦点或点击编辑按钮时,触发一个事件。

同时使用v-class指令,通过CSS隐藏输入框。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接