Vue.js - элемент DOM не удаляется из родительского компонента после изменения маршрута в - PullRequest
1 голос
/ 15 марта 2019

Я столкнулся с непротиворечивым поведением в vue.js и не смог найти никакой документации, описывающей его, и я хотел бы знать, ожидается ли это поведение или нет.

Я разрабатываю SPA с использованием vue.js 2.6.8, @ vue / cli-service 3.5.1 и vue-router 3.0.1.

Мои маршруты выглядят так:

{
    path: '/Users',
    name: 'Users',
    component: Users,
    meta: {requiresAuth: true},
    children: [
        {
            path: 'New',
            component: NewUserModal,
            name: 'NewUserModal',
            meta: {requiresAuth: true},
        }
    ]
},
{
    path: '/Users/:id',
    component: User,
    name: 'User',
    meta: {requiresAuth: true}
}

Компонент Users представляет собой список пользователей, в котором имеется представление маршрутизатора для визуализации модального пользователя, выглядящего следующим образом:

<template>
    <my-list-component>
        <template #modal>
            <router-view/>
        </template>
    </my-list-component>
</template>

Внутри этого компонента пользователь может нажать кнопку, чтобы протолкнуть новый маршрут, NewUserModal , затем отображается модальный режим, в котором можно создать нового пользователя, а после завершения операции происходит еще одно нажатие маршрутизатора, поэтому пользователь перенаправляется на маршрут Пользователь . Короче говоря:

Пользователи -> NewUserModal -> Пользователь

Все этапы NewUserModal происходят, он действительно разрушен. Однако, если я когда-нибудь вернусь к компоненту Users, элемент DOM в NewUserModal все еще будет там, поэтому я вижу DOM уничтоженного дочернего компонента на родительском элементе.

У меня сложилось впечатление, что изменение маршрута произошло "слишком быстро", и когда вызывается метод уничтожения компонента NewUserModal, элемент DOM, который необходимо уничтожить, больше не присутствует на странице, поэтому он не может его удалить.

В качестве обходного пути я поместил следующий код внутри NewUserModal:

    beforeDestroy() {
        this.$el.remove();
    },

И все работает просто отлично. Итак, это ожидаемое поведение vue? Я что-то пропустил? И что еще более важно, я могу ждать удаления DOM прежде, чем изменить маршруты?

Спасибо за ваше время и помощь!

Редактировать 1

Для лучшего понимания мой app.vue поддерживает работу, поэтому все прямые потомки (например, списки пользователей и т. Д.) Не отправляют запрос на сервер каждый раз, когда активируются. Структура App.vue выглядит следующим образом:

<template>
    <keep-alive>
        <router-view/>
    </keep-alive>
</template>

Редактировать 2

В некоторых дальнейших тестах я обнаружил, что обходной путь не работал в 100% случаев, поэтому я изменил обходное решение на это:

async redirectToUser(userId) {
    this.$router.push({name: 'Users'});

    await this.$nextTick();

    this.$router.push({
        name: 'User',
        params: {id: userId}
    });
},

Таким образом, я сначала перенаправляю пользователя к родительскому компоненту, поэтому жизненный цикл дочернего компонента полностью выполняется, а его элементы DOM удаляются, а затем пользователь перенаправляется на компонент User.

Пока работает 100% времени.

1 Ответ

0 голосов
/ 15 марта 2019

Таким образом, при маршруте к user/:id экземпляр компонента будет использоваться повторно. Для любого id - согласно документации.

Может быть Навигация может помочь?

например:

beforeRouteUpdate (to, from, next) {
    // called when the route that renders this component has changed,
    // but this component is reused in the new route.
    // For example, for a route with dynamic params `/foo/:id`, when we
    // navigate between `/foo/1` and `/foo/2`, the same `Foo` component instance
    // will be reused, and this hook will be called when that happens.
    // has access to `this` component instance.
  },

И что еще важнее, можно ли дождаться удаления DOM, прежде чем менять маршруты?

async beforeRouteLeave (to, from, next) {
    // called when the route that renders this component is about to
    // be navigated away from.
    // has access to `this` component instance.

    // maybe wait for next render
    await this.nextTick();
    next()
  }
...