原文网址:Vue--Router--解决多路由复用同一组件页面不刷新问题_IT利刃出鞘的博客-CSDN博客
说明
本文介绍如何解决Vue的多路由复用同一组件页面不刷新问题。
多路由复用同一组件的场景
原因分析
Vue中,相同的组件实例将被重复使用。如果两个路由都渲染同个组件,复用比销毁再创建更高效。不过,复用会导致组件的生命周期函数不会被调用。而我们通常会将调后端接口放到created或mounted等生命周期函数中,生命周期函数没被调用,也就无法获取后端数据。
官网网址
https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#响应路由参数的变化
本处以博客为例。添加博客(path为:/addBlog)和编辑博客(path为:/editBlog)都对应同一个组件(EditBlog.vue)
路由配置(router/index.js)
- import Vue from 'vue'
- import VueRouter from 'vue-router'
- import BlogEdit from '../components/BlogEdit'
-
- Vue.use(VueRouter)
-
- const routes = [
- {
- path: '/addBlog',
- name: 'AddBlog',
- component: BlogEdit
- },
- {
- path: '/editBlog',
- name: 'EditBlog',
- component: BlogEdit
- }
-
- ]
-
- const router = new VueRouter({
- routes
- })
-
- export default router
主页面(App.vue)
- <template>
- <div id="app">
- <div id="nav">
-
-
- <router-link :to="{name: 'AddBlog'}">创建博客router-link>
- |
- <router-link :to="{name: 'EditBlog'}">修改博客router-link>
- div>
- <router-view/>
- div>
- template>
-
- <style>
- style>
博客编辑页(components/BlogEdit.vue)
- <template>
- <div class="outer">
- <div>
- 这是BlogEdit
- div>
- div>
- template>
-
- <script>
- import LifeCycle from '../mixins/LifeCycle'
-
- export default {
- name: 'BlogEdit',
- mixins: [LifeCycle]
- }
- script>
-
- <style scoped>
- .outer {
- margin: 20px;
- border: 2px solid blue;
- padding: 20px;
- }
- style>
混入生命周期(mixins/LifeCycle.js)
我把生命周期的钩子函数单独拿了出来。
- export default {
- computed: {
- name () {
- return this.$options.name
- }
- },
- created () {
- console.log('created ==> ' + this.name)
- },
- activated () {
- console.log('activated ==> ' + this.name)
- },
- deactivated () {
- console.log('deactivated ==> ' + this.name)
- },
- destroyed () {
- console.log('destroyed ==> ' + this.name)
- }
- }

可见,除了第1次进入,之后的进入和退出没有触发相关的生命周期函数,比如:created等。
方法:使用watch监听$route的变化,变化时根据情况请求后端数据。
修改博客编辑组件(components/BlogEdit.vue)
- <template>
- <div class="outer">
- <div>
- 这是BlogEdit
- div>
- div>
- template>
-
- <script>
- import LifeCycle from '../mixins/LifeCycle'
-
- export default {
- name: 'BlogEdit',
- mixins: [LifeCycle],
- watch: {
- $route (to, from) {
- console.log('组件:' + this.$options.name)
- console.log('来自:' + from.name)
- console.log('去往:' + to.name)
- }
- }
- }
- script>
-
- <style scoped>
- .outer {
- margin: 20px;
- border: 2px solid blue;
- padding: 20px;
- }
- style>
测试

可以发现:路由变化时会触发对$route的watch。所以可以将调后端接口的方法放到里边去。
方法:在父组件的router-view中指定key,这个key必须是唯一的,比如:"$route.fullPath"。这样vue就会认为每个内部路由都是不同的,在跳转时便会强制刷新组件。
比如:
<router-view :key="$route.fullPath">router-view>
修改App.vue
- <router-view :key="$route.fullPath">router-view><template>
- <div id="app">
- <div id="nav">
-
-
- <router-link :to="{name: 'AddBlog'}">创建博客router-link>
- |
- <router-link :to="{name: 'EditBlog'}">修改博客router-link>
- div>
-
- <-- <router-view/> -->
- <router-view :key="$route.fullPath">router-view>
- div>
- template>
-
- <style>
- style>
测试

可以发现:可以正常触发组件的生命周期(created、destroyed)。
方法:在beforeRouteEnter中请求后端数据。
导航卫士钩子(mixins/NavigationGuard.js)
为便于管理,我把导航卫士单独拿出来,作为mixin给组件使用。
- export default {
- beforeRouteEnter (to, from, next) {
- // 无法访问this
- console.log('beforeRouteEnter ==> 来自:' + from.path)
- console.log('beforeRouteEnter ==> 去往:' + to.path)
- next(true)
- },
- beforeRouteUpdate (to, from, next) {
- console.log(this.$options.name + ':beforeRouteUpdate ==> 来自:' + from.path)
- console.log(this.$options.name + ':beforeRouteUpdate ==> 去往:' + to.path)
- next(true)
- },
- beforeRouteLeave (to, from, next) {
- console.log(this.$options.name + ':beforeRouteLeave ==> 来自:' + from.path)
- console.log(this.$options.name + ':beforeRouteLeave ==> 去往:' + to.path)
- next(true)
- }
- }
博客编辑组件(components/BlogEdit.vue)
- <template>
- <div class="outer">
- <div>
- 这是BlogEdit
- div>
- div>
- template>
-
- <script>
- import LifeCycle from '../mixins/LifeCycle'
- import NavigationGuard from '../mixins/NavigationGuard'
-
- export default {
- name: 'BlogEdit',
- mixins: [LifeCycle, NavigationGuard]
- }
- script>
-
- <style scoped>
- .outer {
- margin: 20px;
- border: 2px solid blue;
- padding: 20px;
- }
- style>
测试

可见,除了第1次进入,之后的进入和退出没有触发相关的生命周期函数,比如:created等。