Как правильно обновить дочерний компонент в родительском массиве в Vue? - PullRequest
1 голос
/ 06 августа 2020

Я новичок в Vue и надеялся на некоторые разъяснения относительно передовых методов.

Я создаю приложение, которое использует массив для хранения списка дочерних компонентов, и я хочу иметь возможность для обновления и удаления компонентов, передавая их родительскому объекту. Чтобы выполнить sh это, у меня сейчас есть дочерний элемент, проверяющий родительский массив, чтобы найти его индекс с помощью метода «равно», чтобы он мог передать этот индекс родительскому массиву. Это отлично работает для чего-то простого, но если мои дочерние компоненты станут более сложными, будет все больше и больше точек данных, которые мне придется проверять, чтобы убедиться, что я меняю правильный. Я могу придумать еще один способ сделать это - дать дочернему компоненту опору 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>

1 Ответ

1 голос
/ 06 августа 2020

Самое замечательное в 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, как вы предложили).

Ключ к массиву index - это нормально, если ваш массив изменяется только в размере, но если вы когда-нибудь решите splice или sort it, Vue не сможет правильно отреагировать на это изменение, так как индексы никогда не менять.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...