• Vue--Router--解决多路由复用同一组件页面不刷新问题


    原文网址:Vue--Router--解决多路由复用同一组件页面不刷新问题_IT利刃出鞘的博客-CSDN博客

    简介

    说明

    本文介绍如何解决Vue的多路由复用同一组件页面不刷新问题。

    多路由复用同一组件的场景

    1. 多路由使用同一组件
      1. 比如:添加博客(path为:/addBlog)和编辑博客(path为:/editBlog)都对应同一个组件(EditBlog.vue)
    2. 动态路由
      1. 比如:用户详情页采用动态路由,其path为:/user/:id,组件都是UserDetail.vue

    原因分析

    Vue中,相同的组件实例将被重复使用。如果两个路由都渲染同个组件,复用比销毁再创建更高效。不过,复用会导致组件的生命周期函数不会被调用。而我们通常会将调后端接口放到created或mounted等生命周期函数中,生命周期函数没被调用,也就无法获取后端数据。

    官网网址

    https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#响应路由参数的变化

    问题复现

    本处以博客为例。添加博客(path为:/addBlog)和编辑博客(path为:/editBlog)都对应同一个组件(EditBlog.vue)

    代码

    路由配置(router/index.js)

    1. import Vue from 'vue'
    2. import VueRouter from 'vue-router'
    3. import BlogEdit from '../components/BlogEdit'
    4. Vue.use(VueRouter)
    5. const routes = [
    6. {
    7. path: '/addBlog',
    8. name: 'AddBlog',
    9. component: BlogEdit
    10. },
    11. {
    12. path: '/editBlog',
    13. name: 'EditBlog',
    14. component: BlogEdit
    15. }
    16. ]
    17. const router = new VueRouter({
    18. routes
    19. })
    20. export default router

    主页面(App.vue) 

    1. <template>
    2. <div id="app">
    3. <div id="nav">
    4. <router-link :to="{name: 'AddBlog'}">创建博客router-link>
    5. |
    6. <router-link :to="{name: 'EditBlog'}">修改博客router-link>
    7. div>
    8. <router-view/>
    9. div>
    10. template>
    11. <style>
    12. style>

    博客编辑页(components/BlogEdit.vue)

    1. <template>
    2. <div class="outer">
    3. <div>
    4. 这是BlogEdit
    5. div>
    6. div>
    7. template>
    8. <script>
    9. import LifeCycle from '../mixins/LifeCycle'
    10. export default {
    11. name: 'BlogEdit',
    12. mixins: [LifeCycle]
    13. }
    14. script>
    15. <style scoped>
    16. .outer {
    17. margin: 20px;
    18. border: 2px solid blue;
    19. padding: 20px;
    20. }
    21. style>

    混入生命周期(mixins/LifeCycle.js) 

    我把生命周期的钩子函数单独拿了出来。

    1. export default {
    2. computed: {
    3. name () {
    4. return this.$options.name
    5. }
    6. },
    7. created () {
    8. console.log('created ==> ' + this.name)
    9. },
    10. activated () {
    11. console.log('activated ==> ' + this.name)
    12. },
    13. deactivated () {
    14. console.log('deactivated ==> ' + this.name)
    15. },
    16. destroyed () {
    17. console.log('destroyed ==> ' + this.name)
    18. }
    19. }

    测试

    访问:http://localhost:8080/#/

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

    解决方案

    方案1:watch监听$route

    方法:使用watch监听$route的变化,变化时根据情况请求后端数据。

    修改博客编辑组件(components/BlogEdit.vue)

    1. <template>
    2. <div class="outer">
    3. <div>
    4. 这是BlogEdit
    5. div>
    6. div>
    7. template>
    8. <script>
    9. import LifeCycle from '../mixins/LifeCycle'
    10. export default {
    11. name: 'BlogEdit',
    12. mixins: [LifeCycle],
    13. watch: {
    14. $route (to, from) {
    15. console.log('组件:' + this.$options.name)
    16. console.log('来自:' + from.name)
    17. console.log('去往:' + to.name)
    18. }
    19. }
    20. }
    21. script>
    22. <style scoped>
    23. .outer {
    24. margin: 20px;
    25. border: 2px solid blue;
    26. padding: 20px;
    27. }
    28. style>

    测试

    访问:http://localhost:8080/#/

    可以发现:路由变化时会触发对$route的watch。所以可以将调后端接口的方法放到里边去。

    方案2:父组件router-view指定key

    方法:在父组件的router-view中指定key,这个key必须是唯一的,比如:"$route.fullPath"。这样vue就会认为每个内部路由都是不同的,在跳转时便会强制刷新组件。

    比如:

    <router-view :key="$route.fullPath">router-view>

    修改App.vue

    1. <router-view :key="$route.fullPath">router-view><template>
    2. <div id="app">
    3. <div id="nav">
    4. <router-link :to="{name: 'AddBlog'}">创建博客router-link>
    5. |
    6. <router-link :to="{name: 'EditBlog'}">修改博客router-link>
    7. div>
    8. <-- <router-view/> -->
    9. <router-view :key="$route.fullPath">router-view>
    10. div>
    11. template>
    12. <style>
    13. style>

    测试

    访问:http://localhost:8080/#/

    可以发现:可以正常触发组件的生命周期(created、destroyed)。

    无效的方案

    方案1:导航守卫

    方法:在beforeRouteEnter中请求后端数据。

    导航卫士钩子(mixins/NavigationGuard.js)

    为便于管理,我把导航卫士单独拿出来,作为mixin给组件使用。

    1. export default {
    2. beforeRouteEnter (to, from, next) {
    3. // 无法访问this
    4. console.log('beforeRouteEnter ==> 来自:' + from.path)
    5. console.log('beforeRouteEnter ==> 去往:' + to.path)
    6. next(true)
    7. },
    8. beforeRouteUpdate (to, from, next) {
    9. console.log(this.$options.name + ':beforeRouteUpdate ==> 来自:' + from.path)
    10. console.log(this.$options.name + ':beforeRouteUpdate ==> 去往:' + to.path)
    11. next(true)
    12. },
    13. beforeRouteLeave (to, from, next) {
    14. console.log(this.$options.name + ':beforeRouteLeave ==> 来自:' + from.path)
    15. console.log(this.$options.name + ':beforeRouteLeave ==> 去往:' + to.path)
    16. next(true)
    17. }
    18. }

    博客编辑组件(components/BlogEdit.vue)

    1. <template>
    2. <div class="outer">
    3. <div>
    4. 这是BlogEdit
    5. div>
    6. div>
    7. template>
    8. <script>
    9. import LifeCycle from '../mixins/LifeCycle'
    10. import NavigationGuard from '../mixins/NavigationGuard'
    11. export default {
    12. name: 'BlogEdit',
    13. mixins: [LifeCycle, NavigationGuard]
    14. }
    15. script>
    16. <style scoped>
    17. .outer {
    18. margin: 20px;
    19. border: 2px solid blue;
    20. padding: 20px;
    21. }
    22. style>

    测试

    访问: http://localhost:8080/#/

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

  • 相关阅读:
    UUCTF(公共赛道)
    OpenCV17-图像形态学操作
    「Redis」04 发布和订阅
    跨境电商建站:选择域名需要注意什么?
    您这边是个人公众号还是企业公众号哈
    强化学习代码实战(1)
    触摸控件——键盘录入之ASCII录入
    R基本数据类型
    学习《Java核心技术》——第5章:继承
    python matplot画图攻略
  • 原文地址:https://blog.csdn.net/feiying0canglang/article/details/126312672