vue router路由复用及刷新问题研究

路由复用问题

当路由匹配路径未发生变化时,只是相关的参数发生了变化,路由跳转时,会发现虽然地址栏中的地址更新到了新的链接,但是页面渲染并未触发响应路由组件的created,mounted等钩子函数,也就意味着组件并没有被重新创建,也就是路由复用问题。
在官方文档中,下面这段话同样体现了这个问题。
在这里插入图片描述
在这里插入图片描述
了解vue组件复用的应该知道,复用时并不会更新组件内部自身data中拥有的响应式属性,但是如果是通过props传递过来的属性,在复用组件时,进行diff patch时,是会更新的。具体组件复用更新原理不清楚的,可以参考博客组件复用

vue-router在匹配到对应的路由后,同样会更新对应组件的props参数,相关实现逻辑在router-view组件的render函数中有体现,其中fillPropsinData将路由表中的props参数传递给路由组件的props

var configProps = matched.props && matched.props[name];// save route and configProps in cacheif (configProps) {extend(cache[name], {route: route,configProps: configProps});fillPropsinData(component, data, route, configProps);}

具体怎么设置props呢?可以参考官方文档 路由组件传参

props参数复用更新

下面是一个简单的 detail.vue 示例,用于显示详情页面。假设我们通过路由参数 id 来获取并显示特定项的详细信息。

首先,确保你的路由配置中包含了 detail 路由,并且能够传递 id 参数。例如:

// router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import List from '@/page/list.vue';
import Detail from '@/page/detail.vue';Vue.use(Router);export default new Router({routes: [{path: '/list',name: 'List',component: List},{path: '/detail/:id',name: 'Detail',component: Detail}]
});

下面是一个简单的 list.vue 示例,其中包含一个列表,列表项可以跳转到详情页面。假设详情页面的路由为 /detail/:id。

<template><div><ul><li v-for="item in list" :key="item.id" @click="goToDetail(item.id)">{{ item.name }}</li></ul></div>
</template><script>
export default {data() {return {list: [{ id: 1, name: 'Item 1' },{ id: 2, name: 'Item 2' },{ id: 3, name: 'Item 3' },// 更多列表项...]};},methods: {goToDetail(id) {this.$router.push({ path: `/detail/${id}` });}}
};
</script><style scoped>
ul {list-style-type: none;padding: 0;
}li {padding: 8px;cursor: pointer;border-bottom: 1px solid #ccc;
}li:hover {background-color: #f0f0f0;
}
</style>

接下来是 detail.vue 的代码:

<template><div><h1>Detail Page - {{id}} </h1><div v-if="item"><h2>{{ item.name }}</h2><p>ID: {{ item.id }}</p><p>Description: {{ item.description }}</p></div><div v-else><p>Loading...</p></div><button @click="goBack">Back to List</button><button @click="goToDetail">Go to other detail 2</button></div>
</template><script>
export default {props: ['id'],data() {return {item: null};},created() {this.fetchItem();},methods: {fetchItem() {const id = this.$route.params.id;// 假设我们有一个方法来获取数据,这里用模拟数据代替const items = [{ id: 1, name: 'Item 1', description: 'Description for Item 1' },{ id: 2, name: 'Item 2', description: 'Description for Item 2' },{ id: 3, name: 'Item 3', description: 'Description for Item 3' }];this.item = items.find(item => item.id === parseInt(id));},goBack() {this.$router.push({ name: 'List' });},goToDetail() {this.$router.replace({ name: 'Detail', params: { id: 2 } })}}
};
</script><style scoped>
h1 {font-size: 24px;margin-bottom: 20px;
}h2 {font-size: 20px;margin-bottom: 10px;
}p {margin: 5px 0;
}button {margin-top: 20px;padding: 10px 20px;background-color: #007bff;color: white;border: none;cursor: pointer;
}button:hover {background-color: #0056b3;
}
</style>

在这里插入图片描述
从列表跳转到详情页时,可以正常的更新渲染,但是可以到详情页之间互相跳转时,页面的渲染是有问题的。以上面为例,从detail page 3跳转到 detail page 2时,只更新了title 中的id,而对应的内容并没有更新。
在这里插入图片描述
从detail.vue的template中可以看到,组件中props中的id对应的渲染更新了,而item作为组件自身内部响应式并没有更新。因为item的赋值逻辑是在created里触发的,而详情页跳转详情页的情况,是不会触发created的。

渲染更新

如果想让详情页之间的跳转能够及时地更新,要如何做呢?也就是最初上面官网上介绍的,如何响应路由参数的变化?官方给出的方案有相中:

路由守卫

虽然相同路由之间跳转,不会触发created等钩子函数,但是会触发路由守卫函数beforeRouteUpdate,可以考虑将原先的数据初始化逻辑放到这里。以上面的例子为例,可以在代码中加入下面的代码来触发页面的更新:

beforeRouteUpdate (to, from, next) {console.log('=====beforeRouteUpdate====',to.params.id, this.id)this.fetchItem(to.params.id)next()
}
//这里id改为传入的,以便上面方法中能够传入最新的路由参数
fetchItem(id) {// 假设我们有一个方法来获取数据,这里用模拟数据代替const items = [{ id: 1, name: 'Item 1', description: 'Description for Item 1' },{ id: 2, name: 'Item 2', description: 'Description for Item 2' },{ id: 3, name: 'Item 3', description: 'Description for Item 3' }];this.item = items.find(item => item.id === parseInt(id));}

在这里插入图片描述
这里需要注意使用的是beforeRouteUpdate,而不是beforeRouteEnter,经实际验证,beforeRouteEnter只在从其他路由进入该路由时触发,而在像详情页跳转详情页这样的路由复用时,不会触发。

watch监听路由变化

在这里插入图片描述
官网给出的解决方法,除了路由守卫,就是监听$route,加入下面的代码,同样可以达到对应的效果。

watch: {'$route' (to, from) {console.log('=====watch====',to.params.id, this.id)this.fetchItem(to.params.id)}},

打破路由复用

上面的两种方法虽然都能达到路由试图随参数变化而更新,但是本质上还是在复用的基础上,在合适的时机重新触发处理逻辑函数,已达到更新目的。由于是复用的实例,所以在更新时并不会主动销毁之前创建的资源,如果有销毁的需求,比如每次进入详情页都会创建一些canvas等,在路由参数发生变化时,需要重新绘制,通常是需要先销毁之前的,再重新绘制新的,而采用上面两种方法,在复用渲染时,需要我们手动去管理这些。
如果我们期望的是不管路由是不是从详情页跳转详情页复用,每次参数变化时,不复用之前的,销毁之前创建的组件实例,然后重新创建新的组件实例,要如何做呢?
使用 key 强制重新渲染,通过为组件设置一个唯一的 key,Vue 会认为这是一个不同的组件实例,从而强制重新渲染。

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

上面直接在route-view上绑定key值,会影响所有的路由,如果只想针对详情页路由处理,可以直接在组件上使用 key:

<!-- 这里新建一个wrapper.vue 路由组件,修改路由表里的detail路由对应的组件为这个wrapper.vue组件 -->
<template><!-- Detail 组件 --><Detail v-bind="$attrs" :key="$route.params.id"></Detail>
</template>

注意上面直接在路由组件上绑定key值时,需将原有Detail路由组件作为新的路由组件的子组件。因为相同的路径对应的路由还是默认会走vue-router的组件复用逻辑,如果直接在原有的Detail组件内部绑定key值是起不到作用的,这里修改新的路由组件为wrapper.vue组件,复用时也是复用的wrapper组件,在对wrapper组件进行diff算法更新时,由于key值不同,会重新触发子组件的渲染,此时就会重新触发Detail组件的created钩子函数,同时也会触发先前组件的beforeDestroy钩子函数,销毁之前的实例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/68120.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android各个版本存储权限适配

一、Android6.0-9.0 1、动态权限申请&#xff1a; private static String[] arrPermissions {android.Manifest.permission.READ_EXTERNAL_STORAGE, android.Manifest.permission.WRITE_EXTERNAL_STORAGE,android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.…

房租管理系统的智能化应用助推租赁行业高效运营与决策优化

内容概要 在现代租赁行业中&#xff0c;房租管理系统的智能化应用正在逐步成为一个不可或缺的工具。通过整合最新技术&#xff0c;这些系统为租赁管理的各个方面提供了极大的便利和效率提升。从房源管理到合同签署再到财务监控&#xff0c;智能化功能能够帮助运营者在繁琐的事…

数据结构初阶之队列的介绍与队列的实现

一、概念与结构 概念&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出 FIFO (First In First Out) 的特点。 入队列&#xff1a;进行插入操作的一端称为队尾 出队列&#xff1a;进行删除操作的一端称为…

GTO 门级可关断晶闸管,全控性器件

介绍 门级可关断晶闸管是一种通过门极来控制器件导通和关断的电力半导体器件。 结构特点 - 四层半导体结构&#xff1a;与普通晶闸管相似&#xff0c;GTO也是由PNPN四层半导体构成&#xff0c;外部引出三个电极&#xff0c;分别是阳极&#xff08;A&#xff09;、阴极&#x…

FlinkSql使用中rank/dense_rank函数报错空指针

问题描述 在flink1.16(甚至以前的版本)中&#xff0c;使用rank()或者dense_rank()进行排序时&#xff0c;某些场景会导致报错空指针NPE(NullPointerError) 报错内容如下 该报错没有行号/错误位置&#xff0c;无法排查 现状 目前已经确认为bug&#xff0c;根据github上的PR日…

序列标注:从传统到现代,NLP中的标签预测技术全解析

引言 序列标注任务是自然语言处理&#xff08;NLP&#xff09;中的核心任务之一&#xff0c;广泛应用于信息抽取、文本分类、机器翻译等领域。随着深度学习技术的快速发展&#xff0c;序列标注任务的性能得到了显著提升。本文将从基础概念入手&#xff0c;逐步深入探讨序列标注…

CentOS 7 安装fail2ban hostdeny方式封禁ip —— 筑梦之路

centos 7 换源参考CentOS 7.9 停止维护(2024-6-30)后可用在线yum源 —— 筑梦之路_centos停止维护-CSDN博客 安装fail2ban yum install fail2ban 新增配置文件 cat > /etc/fail2ban/action.d/hostsdeny.conf << EOF [Definition] actionstart actionstop action…

速通Docker === Docker Compose

目录 Docker Compose 简介 Docker Compose 常用命令 使用 Docker Compose 启动 WordPress 普通启动方式&#xff08;使用 Docker 命令&#xff09; 使用 Docker Compose 启动 Docker Compose 的特性 Docker Compose 简介 Docker Compose 是一个用于定义和运行多容器 Dock…

关于BAR(PCIE BAR或AXI BAR)的解释

假设某BAR的默认值是xxxx_0000&#xff08;这里表示8个比特位&#xff09;&#xff0c;其中低4位不可写&#xff0c;可操作的最低位是4&#xff0c;所以该BAR的大小是2^416字节&#xff1b; 1、系统软件向BAR写0xFF 2、系统软件读BAR&#xff0c;读到的值是0xF0&#xff0c;于是…

MySQL 事件调度器

MySQL 事件调度器确实是一个更方便且内置的解决方案&#xff0c;可以在 MySQL 服务器端自动定期执行表优化操作&#xff0c;无需依赖外部工具或应用程序代码。这种方式也能减少数据库维护的复杂性&#xff0c;尤其适用于在数据库频繁更新或删除时进行自动化优化。 使用 MySQL …

ESP32服务器和PC客户端的Wi-Fi通信

ESP32客户端-服务器Wi-Fi通信 本指南将向您展示如何设置ESP32板作为服务端&#xff0c;PC作为客户端&#xff0c;通过HTTP通信&#xff0c;以通过Wi-Fi&#xff08;无需路由器或互联网连接&#xff09;交换数据。简而言之&#xff0c;您将学习如何使用HTTP请求将一个板的数据发…

为什么IDEA提示不推荐@Autowired❓️如果使用@Resource呢❓️

前言 在使用 Spring 框架时&#xff0c;依赖注入&#xff08;DI&#xff09;是一个非常重要的概念。通过注解&#xff0c;我们可以方便地将类的实例注入到其他类中&#xff0c;提升开发效率。Autowired又是被大家最为熟知的方式&#xff0c;但很多开发者在使用 IntelliJ IDEA …

如何用数据编织、数据虚拟化与SQL-on-Hadoop打造实时、可扩展兼容的数据仓库?

在大数据技术迅猛发展的背景下&#xff0c;许多人认为传统数据仓库已过时。然而&#xff0c;这种观点忽略了数据仓库的核心价值&#xff1a;统一的数据视图、强大的业务逻辑支撑以及丰富的数据分析能力。在企业数据架构转型中&#xff0c;数据仓库不仅未被淘汰&#xff0c;反而…

15 分布式锁和分布式session

在java中一个进程里面使用synchronized在new出来对象头信息中加锁&#xff0c;如果是静态方法中在加载的类信息中加锁(我们在锁的原理中讲过)。如果使用lock加锁可以自己指定。这些都是在同一个进程空间中的操作。如果在分布式环境中由于程序不在一个进程空间&#xff0c;就没办…

mysql数据被误删的恢复方案

文章目录 一、使用备份恢复二、使用二进制日志&#xff08;Binary Log&#xff09;三、使用InnoDB表空间恢复四、使用第三方工具预防措施 数据误删是一个严重的数据库管理问题&#xff0c;但通过合理的备份策略和使用适当的恢复工具&#xff0c;可以有效地减少数据丢失的风险…

DuckDB:Golang操作DuckDB实战案例

DuckDB是一个嵌入式SQL数据库引擎。它与众所周知的SQLite非常相似&#xff0c;但它是为olap风格的工作负载设计的。DuckDB支持各种数据类型和SQL特性。凭借其在以内存为中心的环境中处理高速分析的能力&#xff0c;它迅速受到数据科学家和分析师的欢迎。在这篇博文中&#xff0…

day1代码练习

输出3-100以内的完美数&#xff0c;(完美数&#xff1a;因子和(因子不包含自身)数本身) #include <stdio.h>// 判断一个数是否为完美数的函数 int panduan(int n) {if (n < 2) {return 0; // 小于2的数不可能是完美数}int sum 1; // 因子和初始化为1&#xff08;因…

dify大模型应用开发平台搭建

原文地址&#xff1a;dify大模型应用开发平台搭建 – 无敌牛 欢迎参观我的技术分享网站&#xff1a;无敌牛 – 技术/著作/典籍/分享等 之前分享了一个私有化部署开源大模型的方法&#xff0c;具体参看往期文章&#xff1a;私有化部署开源AI模型 – 无敌牛 今天搭建一个大模型…

PC端实现PDF预览(支持后端返回文件流 || 返回文件URL)

一、使用插件 插件名称&#xff1a;vue-office/pdf 版本&#xff1a;2.0.2 安装插件&#xff1a;npm i vue-office/pdf^2.0.2 1、“vue-office/pdf”: “^2.0.2”, 2、 npm i vue-office/pdf^2.0.2 二、代码实现 // 引入组件 &#xff08;在需要使用的页面中直接引入&#x…

【统计信号处理基础——估计与检测理论】Vol1.Ch1. 引言

系列目录 【统计信号处理基础——估计与检测理论】Vol1.Ch2. 最小方差无偏估计 文章目录 1. 信号处理中的估计2. 估计的数学问题3. 估计量性能评估习题1.11.21.31.41.5 1. 信号处理中的估计 从离散时间波形或一组数据集中提取参数的问题。我们有 N N N点数据集 { x [ 0 ] , x …