我在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组件是用户列表,其中包含一个router-view,以呈现新的用户模式,如下所示:
<template>
<my-list-component>
<template #modal>
<router-view/>
</template>
</my-list-component>
</template>
在该组件内,用户可以单击按钮以推送新路线NewUserModal,然后显示模式,其中可以创建新用户,并且在操作完成后,将发生另一个路由器推送,因此用户被重定向到用户路线。简而言之:
用户 - > 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元素,然后将用户重定向到用户组件。
到目前为止,100%的工作时间。
因此,当您路由到user/:id
时,组件实例将被重用。对于任何id
-按照文档。
也许Navigation Guards可以帮忙吗?
e.g:
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()
}