Vue.js: дочерние компоненты не перерисовываются - PullRequest
0 голосов
/ 22 сентября 2019

Я пытаюсь разобраться, как реквизиты передаются дочерним компонентам и как они обновляются оттуда.

// parent.vue
<template>
    <div>
        <div v-for="elem in getCurrentArray">
            <child-component :elem="elem"></child-component>
        </div>
        <button @click.prevent="currentIdx--">Prev</button>
        <button @click.prevent="currentIdx++">Next</button>
    </div>
</template>
<script>
    export default {
        components : {
            ChildComponent
        },
        data(){
            return {
                arr : [ ["A", "B", "C" ], [ "D", "E" ]], // this would be populated from vue store
                currentIdx : 0
            }
        },
        computed : {
            getCurrentArray(){
                return this.arr[this.currentIdx]
            }
        },
    }
</script>
// child.vue
<template>
    <div>Prop: {{elem}} <input type="text" v-model="myinput" @blur="save" /></div>
</template>
<script>
    export default {
        props : [ "elem" ],
        data(){
            return {
                myinput : this.elem
            }
        },
        methods : {
            save(){
               // this.$store.dispatch("saveChildElement", { myinput }
            }
        },
        mounted(){ console.log( this.elem + " being rendered" ) }
    }
</script>

В этом примере у меня есть два набора массивов [«A», «B», «C»] и [«D», «E»].При загрузке страницы первый набор отображается через дочерние компоненты.

On page load

выглядит хорошо.Однако, когда я нажимаю «Далее», чтобы перейти ко второму набору, я получаю следующее: enter image description here

Таким образом, при правильной передаче реквизитов входные значения текстового поля не обновляются.Когда я проверил console.log, стало ясно, что vue не выполняет рендеринг дочерних компонентов для «D» и «E».Вместо этого он просто использует существующие компоненты для «A» и «B».

Есть ли способ заставить vue перерисовать компоненты?Если нет, то как я могу убедиться, что для ввода в текстовое поле получены последние значения проп?Имейте в виду, что я хочу сохранить изменения входных значений через хранилище vue.

Ответы [ 4 ]

2 голосов
/ 22 сентября 2019

Добавьте ключ, как говорит крутой человек, это решит проблему.

Однако ваша проверка на повторную визуализацию компонента имеет недостатки, вы использовали дочерний смонтированный жизненный цикл, и потому что вы видите, что он работаеттолько когда вы думаете, что компонент не перерисовывается.Но это неправильно.«смонтированный» происходит только один раз в жизненном цикле компонента, и поскольку вы используете один и тот же компонент для ['A', 'B', 'C'], а затем для ['D', 'E'] vue не знаетвоссоздать компоненты и просто перерисовать их с новыми реквизитами.

1 голос
/ 22 сентября 2019

Вы можете запросить повторную визуализацию вашего компонента.(Другие ответы об обновлении ключа верны).

Однако, если вы действительно хотите использовать Vuex для управления состоянием, я предлагаю вам сделать это в первую очередь, поскольку существует (по сути) другой механизм, который будет это делатьперерисовать для вас, и чувствовать себя намного легче.А именно «вычисленные свойства», скорее всего, решат это за вас.

Я помню, как застрял на этом, когда начинал, и как только я внедрил Vuex, мне хотелось, чтобы я просто сделал это таким образом, что как бы решило проблему для меня как часть его рабочего процесса.(Это, вероятно, будет означать, что вам не нужно обновлять ключ, но у вас это есть, если у вас сложная ситуация, когда вам все еще нужно форсировать повторную визуализацию).

Редактировать: Как правильно заметил @JonyB, вы пытаетесь повторно визуализировать весь компонент.Если вы подумаете об этом, то, что вы действительно хотите здесь сделать, это не перерисовать весь компонент, а просто обновить состояние.Поэтому, как только вы внедрите Vuex, он, скорее всего, решит это за вас, поскольку позволит вам работать с состоянием отдельно.

1 голос
/ 22 сентября 2019

Все, что вам нужно, чтобы добавить key в цикл v-for, и он будет работать.

Заменить

<div v-for="elem in getCurrentArray">

на

<div v-for="elem in getCurrentArray" :key="elem">

Ссылка: https://vuejs.org/v2/guide/list.html#v-for-with-a-Component

1 голос
/ 22 сентября 2019

Попробуйте добавить :Key реквизит в цикле v-for

<div v-for="elem in getCurrentArray" :key="elem">

Чтобы дать Vue подсказку, чтобы он мог отслеживать идентичность каждого узла и, таким образом, повторно использовать и переупорядочивать существующие элементы, вам необходимо предоставить уникальный атрибут ключа для каждого элемента:

... Отображение списка - сохранение состояния

Ключи должны быть уникальными, если у вас естьдва или более одинаковых значения в вашем массиве, например ['A',' B', 'A'], это создаст конфликт, лучший способ преодолеть это - добавить сгенерированный уникальный 'ID' для каждого экземпляра.

Или В альтернативе (краткосрочное решение)

Вы можете использовать индекс цикла в сочетании со значением массива, это должно дать вам более или менее уникальный ключ.

<div v-for="(elem, index) in getCurrentArray" :key="elem + index">

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