Vue Router解决多路由复用同一组件页面不刷新问题(场景分析)

目录
  • 简介
  • 问题复现
    • 代码
    • 测试
  • 解决方案
    • 方案1:导航守卫
    • 方案2:watch监听$route
    • 方案3:父组件router-view指定key
  • 其他网址

简介

说明

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

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

  • 多路由使用同一组件

    比如:添加博客(path为:/addBlog)和编辑博客(path为:/editBlog)都对应同一个组件(EditBlog.vue)
  • 动态路由

    比如:用户详情页采用动态路由,其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)

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="/">Home</router-link> |-->
      <!--<router-link to="/about">About</router-link>-->
      <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)
  }
}

测试

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

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

解决方案

方案1:导航守卫

方法:在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>

测试

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

可以发现:离开路由时会调用beforeRouteLeave,进入路由时会调用beforeRouteEnter。所以可以将调后端接口的方法放到beforeRouteEnter里边去。

方案2:watch监听$route

方法:使用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>

测试

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

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

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

方法:在父组件的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="/">Home</router-link> |-->
      <!--<router-link to="/about">About</router-link>-->
      <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>

测试

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

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

其他网址

Vue keepAlive实现不同的路由共用一个组件component的缓存问题

到此这篇关于VueRouter解决多路由复用同一组件页面不刷新问题的文章就介绍到这了,更多相关VueRouter复用同一组件页面不刷新内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue Router应用方法详解

    目录 服务端路由 路由的应用场景 路由 监听浏览器 hashchange 事件实现路由 使用Vue Router+Vue2实现路由 服务端路由 服务端路由时指的是服务器根据用户访问的 URL 路径返回不同的响应结果. 在传统的服务端渲染的 web 应用中点击一个链接时,浏览器会从服务端获得全新的 HTML页面,然后重新加载整个页面. 然而,在单页面应用中,客户端的 JavaScript 可以拦截页面的跳转请求,动态获取新的数据,无需重新加载的情况下更新当前页面. 这样通常可以带来更顺滑的用户体验

  • 使用vue-router切换组件时使组件不销毁问题

    目录 vue-router切换组件时使组件不销毁 1.用keep-alive包裹router-view 2.定义路由meta字段 3.keep-alive的原理 vue-router路由切换 组件重用挖下的坑 问题描述 翻车现场再现 车祸原因分析 前往救援 一次真的救援 vue-router切换组件时使组件不销毁 默认地,使用vue-router切换组件时,离开的组件会被销毁,新进入地组件会创建. 那么,有时候,我们希望离开的组件不要被销毁.这时就需要使用到keep-alive标签来缓存组件.

  • Vue Router嵌套路由(children)的用法小结

    目录 简介 使用场景 官网网址 示例 路由配置 用户页面(父页面) 子路由的path前加“/” 简介 说明 本文介绍Vue Router的嵌套路由的用法. 嵌套路由就是父路由里面嵌套他的子路由,父路由有自己的路由导航和路由容器(router-link.router-view),通过配置children可实现多层嵌套.(router-view必须要有,否则点击了router-link后,路径会变化,但页面不改变). 使用场景 嵌套路由用于实现页中页效果.例如: 用户页面中,有登录页面和注册页面,这

  • vue-router中关于children的使用方法

    目录 关于children的使用 children的使用场景 router配置中children配置不起作用 关于children的使用 children的使用场景 比如页面左侧显示菜单,右侧显示不同菜单下的内容,类似如下element网站,那么右侧部分的内容就是当前页面的children 存在如下场景,点击导航一跳转至页面1,导航二跳转页面2,且页面1中存在子页面 路由js如下: const routes = [{ path: '/', name: 'Home', component: Hom

  • Vue cli及Vue router实例详解

    目录 前言: 1. 安装 1.1 npm安装 1.2 vue-cli安装 2. 初始化项目 2.1vue init命令讲解 2.2 项目初始化 3. 运行项目 4. 成功页面 5. 项目结构 5.1 总体框架 5.2 配置目录文件详解 5.3src项目核心文件讲解 6. VUE-ROUTER 6.1 快速入门 6.2 页面跳转 6.3子路由-路由嵌套 6.4路由传递参数 6.5命名路由-命名视图-重定向-别名 前言: 官方文档 vue-cli是vue官方出品的快速构建单页应用的脚手架,里面集成了

  • 关于VueRouter导入的全过程

    目录 router nanoid的使用 引入 使用 路由 1-1 安装依赖 1-2 引入 1-3 在main.js中使用 1-4 App.vue 全局过滤器 element-ui 全局组件 Vuc-cli中的视配 1-1 安装依赖 1-2 配置文件 1-3 main.js 1-4 public/index.html 1-5 在pc端视配 slot封装动画 项目初始化 1-1 .router-link-active 1-2 动态显示tabbar 1-3 跳转回前一个页面 1-4轮播 vant ui

  • Vue Router深扒实现原理

    目录 回顾Vue Router的核心代码 代码实现 创建Vue-Router插件 构造函数 完整代码 Vue Router官网 前置知识:插件.slot插槽.mixins混入.render函数.运行时和完整版的Vue 回顾Vue Router的核心代码 // 注册插件 // Vue.use() 内部调用传入对象的 install 方法 Vue.use(VueRouter) // 创建路由对象 const router = new VueRouter({ routes: [ { name: 'ho

  • Vue Router解决多路由复用同一组件页面不刷新问题(场景分析)

    目录 简介 问题复现 代码 测试 解决方案 方案1:导航守卫 方案2:watch监听$route 方案3:父组件router-view指定key 其他网址 简介 说明 本文介绍如何解决Vue的多路由复用同一组件页面不刷新问题. 多路由复用同一组件的场景 多路由使用同一组件 比如:添加博客(path为:/addBlog)和编辑博客(path为:/editBlog)都对应同一个组件(EditBlog.vue) 动态路由 比如:用户详情页采用动态路由,其path为:/user/:id,组件都是User

  • Vue Router 实现动态路由和常见问题及解决方法

    个人理解:动态路由不同于常见的静态路由,可以根据不同的「因素」而改变站点路由列表.常见的动态路由大都是用来实现:多用户权限系统不同用户展示不同导航菜单. 如何利用Vue Router 实现动态路由 Vue项目实现动态路由的方式大体可分为两种: 前端将全部路由规定好,登录时根据用户角色权限来动态展示路由: 路由存储在数据库中,前端通过接口获取当前用户对应路由列表并进行渲染: 第一种方式在很多Vue UI Admin上都实现了,可以去读一下他们的源码理解具体的实现思路,这里就不过多展开.第二种方式现

  • Vue模拟数据,实现路由进入商品详情页面的示例

    一.路由 首先需要配置路由,就是点击good组件进入goodDetail组件 配置路由如下 { path: '/goodDetail', component:goodDetail } 同时在good组件中写入如下点击事件,路由中加入查询参数,也就是商品的id //点击路由到商品详细信息页 selectGood(){ router.push({ path: 'goodDetail', query:{goodId:this.goodDetail.id}}) } 二.在goodDetail组件中接收路

  • 解决webview 第二次调用loadUrl页面不刷新的问题

    一个需求,当点击Button按钮时,希望加载另一个Url. 以下方法可以成功! @Override public void onClick(View view) { webview.loadUrl(url); webview.loadUrl( "javascript:window.location.reload( true )" ): } 亲测管用! 补充知识:WebView.loadUrl使用误区 当使用loadUrl加载网页的时候,有时候会出现调用系统浏览器加载网页的现象,网上大部

  • vue 点击按钮 路由跳转指定页面的实现方式

    目录 点击按钮 路由跳转指定页面 最终效果 vue跳转页面常用的方式 1:router-link跳转 2:this.$router.push() 3.this.$router.replace() 4.this.$router.go(n) ps : 区别 点击按钮 路由跳转指定页面 最终效果 点击指定按钮,跳转指定 /login 页面 代码: <button @click="gotolink" class="btn btn-success">点击跳转页面&

  • vue中内嵌iframe的src更新页面未刷新问题及解决

    目录 vue内嵌iframe的src更新页面未刷新 原因 解决 iframe的src指向的内容不刷新的解决方法之一 总结 vue内嵌iframe的src更新页面未刷新 vue中,系统使用iframe内嵌了其他系统的页面,iframe的src修改了,但是iframe内部页面内容未更新,也未请求接口. 原因 iframe的src中如果带hash #,src改变是不会刷新的. 解决 方式一:可以在 # 号前加一个随机数或者时间戳,但这种方式会改变url:方式二:在组件上加key,强制刷新页面. 方式一

  • React中路由参数如何改变页面不刷新数据的情况

    目录 React路由参数改变页面不刷新数据的情况 React页面路由 前端路由和后端路由 前端路由介绍 匹配模式 路由的执行过程 hash模式 history模式 react-router-dom API React路由参数改变页面不刷新数据的情况 路由的参数由于是在componentDidMount中获取的,如果在详情页面再次打开详情页面,由于组件并没有重新渲染,导致didMount不会获取路由参数. 因此在参数改变的时候,可以利用componentWillReceiveProps来更新变量.

  • Vue keepAlive实现不同的路由共用一个组件component的缓存问题(推荐)

    不同的路由共用一个组件component,并用keepAlive实现不同的页面缓存 实现功能:使用列表页面检索的数据跳转到对应的详情页面,从详情页回到列表页能记住上次检索的数据,再次切换到详情页时能正常取到对应的数据 实现方式使用Vue keepAlive实现页面缓存,整理了一些资料和其他的博客在这里记录一下.... keepAlive原理: 1,保留组件的状态,在重新进入页面时避免重新渲染.2.是抽象组件,它自身不会渲染DOM元素,也不会出现在父组件链中.3.当组件在 内被切换,它的 acti

  • vue.js Router中嵌套路由的实用示例

    前言 随着 Vue.js 单页应用(SPA)变得相当复杂,你开始需要 Vue 路由以及嵌套路由.嵌套路由允许更复杂的用户界面以及相互嵌套的组件.让我们创建一个相对简单的用例,来展示 Vue Router 中嵌套路由的实用性. 用 Vue CLI 进行设置 如果尚未安装,请运行以下命令全局安装 Vue CLI: $ npm install -g @vue/cli 或者 $ yarn global add @vue/cli 现在你能从命令行运行 vue 命令了.让我们创建一个名为 alligator

随机推荐