首页 > 解决方案 > 在Vue中更新父数组中的子组件的正确方法是什么?

问题描述

我是 Vue 的新手,希望能对最佳实践进行一些澄清。

我正在构建一个使用数组来保存子组件列表的应用程序,并且我希望能够通过向父组件发出来更新和删除组件。为了做到这一点,我目前让孩子检查父数组以使用“equals”方法找到它的索引,以便它可以将该索引传递给父数组。这对于一些简单的事情很好,但是如果我的子组件变得更复杂,我将不得不检查越来越多的数据点以确保我正在更改正确的数据点。我能想到的另一种方法是在创建子组件时给它一个 ID 道具,然后传递它,但是我必须确保所有的 id 都不同。

我是在正确的轨道上还是有更好的更广泛接受的方法来做到这一点?我也尝试过使用 indexOf(this._props) 来获取索引,但这似乎不起作用。也许我只是做错了什么?

这是我正在做的简化版本:

// fake localStorage for snippet sandbox
const localStorage = {}

Vue.component('child', {
    template: '#template',
    data() {
        return {
            newName: this.name
        }
    },
    props: {
        name: String
    },
    mounted() {
        this.newName = this.name
    },
    methods: {
        update() {
            this.$emit(
                "update-child",
                this.$parent.children.findIndex(this.equals),
                this.newName
            )
        },
        equals(a) {
            return a.name == this.name
        }
    }
})

var app = new Vue({
    el: '#app',
    data: {
        children: []
    },
    methods: {
        addNewChild() {
            this.children.push({
                name: 'New Child',
            })
        },
        updateChild(index, newName) {
            this.children[index].name = newName
        }
    },
    mounted() {
        if (localStorage.children) {
            this.children = JSON.parse(localStorage.children)
        }
    },
    watch: {
        children(newChildren) {
            localStorage.children = JSON.stringify(newChildren)
        }
    }
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<div id="app">
    <button v-on:click="addNewChild">+ New Child</button>
    <hr />
    <child v-for="child in children"
        :key="children.indexOf(child)"
        :name="child.name"
        @update-child="updateChild">
    </child>
</div>

<script type="text/x-template" id="template">
    <div>
        <p><b>Name: {{name}}</b></p>
        <input placeholder="Name" type="text" v-model="newName" />
        <button @click="update">Update</button>
        <hr />
    </div>
</script>

标签: javascripthtmlvue.js

解决方案


最棒的v-for是它创建了自己的范围。考虑到这一点,您可以安全地child在事件处理程序中引用。例如

<child 
  v-for="(child, index) in children"
  :key="index"
  :name="child.name"
  @update-child="updateChild(child, $event)"
/>
updateChild(child, newName) {
  child.name = newName
}

您需要从子组件发出的只是新名称,它将作为事件有效负载呈现$event

update() {
  this.$emit("update-child", this.newName)
}

关于:key...的快速说明肯定会更好地键入child对象的某些独特属性(如id您所建议的那样)。

如果您的数组仅在大小上发生变化,则键入数组索引很好,但如果您决定拼接排序它,Vue 将无法正确响应该更改,因为索引永远不会改变。


推荐阅读