【问题标题】:Vue.js - DOM element not removed from parent component after route change inVue.js - 路由更改后未从父组件中删除 DOM 元素
【发布时间】:2019-08-06 02:59:00
【问题描述】:

我在 vue.js 中遇到了一致的行为,找不到任何描述它的文档,我想知道这种行为是否是预期的。

我正在使用 vue.js 2.6.8、@vue/cli-service 3.5.1 和 vue-router 3.0.1 开发 SPA。

我的路线如下所示:

{
    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,然后会显示一个模式,可以创建一个新用户,操作完成后会发生另一个路由推送,所以用户被重定向到 User 路由。简而言之:

用户 -> NewUserModal -> 用户

NewUserModal 的所有阶段都会发生,它确实被破坏了。但是,如果我回到 Users 组件,NewUserModal 的 DOM 元素仍然存在,所以我会在父组件上看到被破坏的子组件的 DOM。

我的印象是路由更改发生“太快”,并且当调用 NewUserModal 组件的destroy方法时,页面中不再存在它需要销毁的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% 的时间都在工作。

【问题讨论】:

  • “但是,如果我回到用户组件” ????你怎么“回去”
  • 您可以尝试更改为&lt;router-view :key="$route.fullPath"&gt;&lt;/router-view&gt;。见What is <router-view :key=“$route.fullPath”> ?
  • 显然,组件User 是组件Users 的子组件。可以加进去看看吗?
  • @Phil 所有的路由变化都是通过推送发生的,例如:this.$router.push({name: 'User'});
  • @varit05 我可能错了,但事实并非如此。组件用户是用户列表,组件用户是单个用户的详细信息。 User 不是子路由,因为它不依赖于 Users 组件,它实际上是一个完全不同的页面。如果我将用户添加为用户的子路由,我将不得不处理用户列表,这不应该显示。

标签: dom vue.js vue-router vue-cli-3


【解决方案1】:

因此,当您路由到 user/:id 时,组件实例将被重用。 对于任何id- 根据文档。

也许Navigation Guards 可以帮忙?

例如:

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()
  }

【讨论】:

  • 我尝试了这种方法,不幸的是,NewUserModal 的 DOM 元素仍然显示在用户组件中。
  • 从 2017 年发现这个,不确定这是否真的是你所经历的:forum.vuejs.org/t/…
  • 是的,我们最终在同一个地方。这就是我得到修复的方式。后来我更新了一种新方法,这样做:this.$router.push({name: 'Users'}); await this.$nextTick(); this.$router.push({name: 'User'});
猜你喜欢
  • 2020-07-07
  • 2021-09-01
  • 1970-01-01
  • 2019-05-29
  • 1970-01-01
  • 2017-10-22
  • 1970-01-01
  • 1970-01-01
  • 2016-07-07
相关资源
最近更新 更多