简体   繁体   English

在Vue中更新父数组中的子组件的正确方法是什么?

[英]What's the proper way to update a child component in the parent's array in Vue?

I'm new to Vue and was hoping for some clarification on best practices.我是 Vue 的新手,希望能对最佳实践进行一些澄清。

I'm building an app that uses an array to keep a list of child components and I want to be able to update and remove components by emiting to the parent.我正在构建一个使用数组来保存子组件列表的应用程序,并且我希望能够通过向父组件发出来更新和删除组件。 To accomplish this I currently have the child check the parent array to find it's index with an "equals" method so that it can pass that index to the parent.为了做到这一点,我目前让孩子检查父数组以使用“equals”方法找到它的索引,以便它可以将该索引传递给父数组。 This works fine for something simple but if my child components get more complex, there will be more and more data points I'll have to check to make sure I'm changing the correct one.这对于一些简单的事情很好,但是如果我的子组件变得更复杂,我将不得不检查越来越多的数据点以确保我正在更改正确的数据点。 Another way to do this that I can think of is to give the child component an ID prop when it's made and just pass that but then I'd have to handle making sure all the ids are different.我能想到的另一种方法是在创建子组件时给它一个 ID 道具,然后传递它,但是我必须确保所有的 id 都不同。

Am I on the right track or is there a better more widely accepted way to do this?我是在正确的轨道上还是有更好的更广泛接受的方法来做到这一点? I've also tried using indexOf(this._props) to get the index but that doesn't seem to work.我也尝试过使用 indexOf(this._props) 来获取索引,但这似乎不起作用。 Maybe I'm just doing something wrong?也许我只是做错了什么?

Here's a simplified version of what I'm doing:这是我正在做的简化版本:

 // 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>

The great thing about v-for is that it creates its own scope. v-for的伟大之处在于它创建了自己的 scope。 With that in mind, you can safely reference child in the event handler.考虑到这一点,您可以在事件处理程序中安全地引用child For example例如

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

All you need to emit from your child component is the new name which will be presented as the event payload $event您需要从子组件发出的只是新名称,它将作为事件有效负载$event呈现

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

A quick note about :key ... it would definitely be better to key on some unique property of the child object (like an id as you suggested).关于:key ... 的简短说明肯定会更好地键入child object 的某些独特属性(如您建议的id )。

Keying on array indices is fine if your array only changes in size but if you ever decide to splice or sort it, Vue won't be able to react to that change correctly since the indices never change.如果您的数组仅在大小上发生变化,则键入数组索引很好,但如果您决定拼接排序它,Vue 将无法正确响应该更改,因为索引永远不会改变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM