Vue 改变路由时重新创建父组件
Vue re-creates the parent component when changes routes
我在项目中使用 Vue.js 和 Vue-router,问题是当路由更改时,包含 router-view 的组件被破坏。这意味着页面上的所有其他组件都被销毁,所以整个事情看起来像页面刷新。
我最近开始使用 Vue,我正在处理的应用程序充满了很多遗留代码,很难减少到基础,所以我很难隔离问题。
我试图在 fiddle 中重现该问题,但没有成功。
这是模板代码:
<div id="router-app">
<router-view></router-view>
</div>
<template id="tricky-place">
<div>
<h1>Tricky place</h1>
<ul>
<li>
<router-link to="/panel1">Panel1</router-link>
</li>
<li>
<router-link to="/panel2">Panel2</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</template>
<template id="tricky-place-panel1">
<div>
<h2>Panel1</h2>
</div>
</template>
<template id="tricky-place-panel2">
<div>
<h2>Panel2</h2>
</div>
</template>
和脚本:
const TrickyPlace = Vue.component('tricky-place', {
created() {
console.log("TrickyPlace - created");
},
mounted() {
console.log("TrickyPlace - mounted");
},
updated() {
console.log("TrickyPlace - updated");
},
destroyed() {
console.log("TrickyPlace - destroyed");
},
template: '#tricky-place'
});
const TrickyPlacePanel1 = Vue.component('tricky-place-panel1', {
created() {
console.log("TrickyPlacePanel1 - created");
},
mounted() {
console.log("TrickyPlacePanel1 - mounted");
},
updated() {
console.log("TrickyPlacePanel1 - updated");
},
destroyed() {
console.log("TrickyPlacePanel1 - destroyed");
},
template: '#tricky-place-panel1'
});
const TrickyPlacePanel2 = Vue.component('tricky-place-panel2', {
created() {
console.log("TrickyPlacePanel2 - created");
},
mounted() {
console.log("TrickyPlacePanel2 - mounted");
},
updated() {
console.log("TrickyPlacePanel2 - updated");
},
destroyed() {
console.log("TrickyPlacePanel2 - destroyed");
},
template: '#tricky-place-panel2'
});
const routes = [{
path: '/',
component: TrickyPlace,
children: [{
path: 'panel1',
component: TrickyPlacePanel1
}, {
path: 'panel2',
component: TrickyPlacePanel2
}, ]
}]
const router = new VueRouter({
routes
});
const routerApp = new Vue({
router,
el: '#router-app',
});
这是 fiddle:https://jsfiddle.net/loorker/m1hncLb0/15/
这是我加载 fiddle 时的控制台日志,点击 Panel1,然后点击 Panel2:
TrickyPlace - created
TrickyPlace - mounted
TrickyPlacePanel1 - created
TrickyPlacePanel1 - mounted
TrickyPlace - updated
TrickyPlacePanel2 - created
TrickyPlacePanel1 - destroyed
TrickyPlacePanel2 - mounted
TrickyPlace - updated
这符合预期。
下面是当我 运行 我的应用程序中的相同代码时相同操作序列的控制台日志:
TrickyPlace - created
TrickyPlace - mounted
TrickyPlace - created
TrickyPlacePanel1 - created
TrickyPlace - destroyed
TrickyPlacePanel1 - mounted
TrickyPlace - mounted
TrickyPlace - created
TrickyPlacePanel2 - created
TrickyPlacePanel1 - destroyed
TrickyPlace - destroyed
TrickyPlacePanel2 - mounted
TrickyPlace - mounted
TrickyPlace 在每次路线更改时被销毁并创建,而不是像 fiddle 中那样被更新。
换句话说,考虑到 https://vuejs.org/v2/guide/instance.html 中的数字,在我的应用程序中发生的情况是,在表示已安装的红色圆圈中,执行流程不采用 "when data changes" 路径,而是直接到 "when vm.$destroy() is called".
我尝试将路由器的模式设置为 "history" 但它的行为是一样的。应用程序中的任何地方都没有调用 $destroy() 。我没有在路由器视图上设置 :key 绑定。
关于我如何继续查找问题的任何想法,为什么为父调用 created/destroy 而不是仅仅更新?
谢谢。
刚发现问题。在组件层次结构中有一个 <router-view>
,其中 :key="$route.fullPath"
更高...
如所述:
If you bind key
to $route.fullPath
, it will always "force
a replacement" of the <router-view>
element / component every
time a navigation event occurs.
我在项目中使用 Vue.js 和 Vue-router,问题是当路由更改时,包含 router-view 的组件被破坏。这意味着页面上的所有其他组件都被销毁,所以整个事情看起来像页面刷新。
我最近开始使用 Vue,我正在处理的应用程序充满了很多遗留代码,很难减少到基础,所以我很难隔离问题。
我试图在 fiddle 中重现该问题,但没有成功。 这是模板代码:
<div id="router-app">
<router-view></router-view>
</div>
<template id="tricky-place">
<div>
<h1>Tricky place</h1>
<ul>
<li>
<router-link to="/panel1">Panel1</router-link>
</li>
<li>
<router-link to="/panel2">Panel2</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</template>
<template id="tricky-place-panel1">
<div>
<h2>Panel1</h2>
</div>
</template>
<template id="tricky-place-panel2">
<div>
<h2>Panel2</h2>
</div>
</template>
和脚本:
const TrickyPlace = Vue.component('tricky-place', {
created() {
console.log("TrickyPlace - created");
},
mounted() {
console.log("TrickyPlace - mounted");
},
updated() {
console.log("TrickyPlace - updated");
},
destroyed() {
console.log("TrickyPlace - destroyed");
},
template: '#tricky-place'
});
const TrickyPlacePanel1 = Vue.component('tricky-place-panel1', {
created() {
console.log("TrickyPlacePanel1 - created");
},
mounted() {
console.log("TrickyPlacePanel1 - mounted");
},
updated() {
console.log("TrickyPlacePanel1 - updated");
},
destroyed() {
console.log("TrickyPlacePanel1 - destroyed");
},
template: '#tricky-place-panel1'
});
const TrickyPlacePanel2 = Vue.component('tricky-place-panel2', {
created() {
console.log("TrickyPlacePanel2 - created");
},
mounted() {
console.log("TrickyPlacePanel2 - mounted");
},
updated() {
console.log("TrickyPlacePanel2 - updated");
},
destroyed() {
console.log("TrickyPlacePanel2 - destroyed");
},
template: '#tricky-place-panel2'
});
const routes = [{
path: '/',
component: TrickyPlace,
children: [{
path: 'panel1',
component: TrickyPlacePanel1
}, {
path: 'panel2',
component: TrickyPlacePanel2
}, ]
}]
const router = new VueRouter({
routes
});
const routerApp = new Vue({
router,
el: '#router-app',
});
这是 fiddle:https://jsfiddle.net/loorker/m1hncLb0/15/
这是我加载 fiddle 时的控制台日志,点击 Panel1,然后点击 Panel2:
TrickyPlace - created
TrickyPlace - mounted
TrickyPlacePanel1 - created
TrickyPlacePanel1 - mounted
TrickyPlace - updated
TrickyPlacePanel2 - created
TrickyPlacePanel1 - destroyed
TrickyPlacePanel2 - mounted
TrickyPlace - updated
这符合预期。
下面是当我 运行 我的应用程序中的相同代码时相同操作序列的控制台日志:
TrickyPlace - created
TrickyPlace - mounted
TrickyPlace - created
TrickyPlacePanel1 - created
TrickyPlace - destroyed
TrickyPlacePanel1 - mounted
TrickyPlace - mounted
TrickyPlace - created
TrickyPlacePanel2 - created
TrickyPlacePanel1 - destroyed
TrickyPlace - destroyed
TrickyPlacePanel2 - mounted
TrickyPlace - mounted
TrickyPlace 在每次路线更改时被销毁并创建,而不是像 fiddle 中那样被更新。
换句话说,考虑到 https://vuejs.org/v2/guide/instance.html 中的数字,在我的应用程序中发生的情况是,在表示已安装的红色圆圈中,执行流程不采用 "when data changes" 路径,而是直接到 "when vm.$destroy() is called".
我尝试将路由器的模式设置为 "history" 但它的行为是一样的。应用程序中的任何地方都没有调用 $destroy() 。我没有在路由器视图上设置 :key 绑定。
关于我如何继续查找问题的任何想法,为什么为父调用 created/destroy 而不是仅仅更新?
谢谢。
刚发现问题。在组件层次结构中有一个 <router-view>
,其中 :key="$route.fullPath"
更高...
如所述
If you bind
key
to$route.fullPath
, it will always "force a replacement" of the<router-view>
element / component every time a navigation event occurs.