react 回退到前一页面对应位置

本文分享了解决React应用中页面跳转后返回原位置的问题,通过在Redux中保存滚动位置,实现在返回时恢复到跳转前的位置,提升用户体验。

  由于react的在跳转页面的时候,实际做了unmount的动作,清楚了前一页面的内容,返回的时候实际上是需要重新渲染的,相应的跳转位置就会丢失。我再做项目开发的过程中也遇到了相同的问题,我把我解决的过程分享给大家,希望能够帮到你。

 解决问题的技术背景

1.我们的app是使用了上啦加载下啦刷新的插件(自己封装的),采用的是固定的高度(屏幕高度),自定义滚动轴(非浏览器滚动轴),这个插件会实时的记录滚动位置。

2.APP首页分为十一个子模块,每个子模块都有一个接口去拉取对应模块的数据,拉取完成后会将数据存储到redux里面

3.首页的每个模块都有很多链接跳转到其他页面(商品列表,商品详情,活动专题页面,快速下单页面等)

4.app使用的技术栈react + redux + react-router 

存在的问题以及要解决的问题

1.首页滚动后跳转到其他页面,然后点击返回的时候,首页又重新回到了首页,如果已经滚动了十几页,客户再访问的时候又需要重新滚动到下面,体验很差,运营希望解决掉这个问题,返回的时候还返回到对应跳走的位置,不仅仅是首页 也包括(产品列表页,专题页面,快速下单页面,文章列表页面等)

解决过程

解决思路如下

1.我采用的是把数据先全部保存到redux里面,减少返回重新请求服务器的次数,也减少请求服务器的时间

2.在页面跳转的时候,由于首页,列表页,快速下单,以及其他的列表页面我都引入了上啦加载下拉刷新组件(我再后面的介绍中撑为pullload),在pulload中实际上是有实时将scroll位置记录到redux里面的,所以我只要在pullload 卸载(unmount)的时候将scroll位置以及对应的页面记录到redux里面就可以了。

3.在history.back的时候,判断redux里面是否有当前页面的值,如果有取出来

4.在 componentDidMount中判断是否有对应的scroll值,如果有,则 在setTimeout中调用pulload的moveTo方法滚动到对应位置

5.因为直接pullLoad到对应位置会先展示页面的头部在跳转到对应位置,先的很生硬,所以我再state中加了一个visibility:visible状态变量,滚动到对应位置后,200秒延迟将页面显示出来

 

 

<think> 首先,用户的问题是关于小程序中页面回退时mounted函数不执行的解决方案。用户指定了“小程序”,所以我需要针对uni-app或微信小程序等环境来回答,因为它们是小程序开发框架。 从用户提供的引用中: - 引用[1]讨论了React的错误边界和函数组件的优化,但用户的问题是关于小程序的,React不直接相关。 - 引用[2]是关于uni-app的,提到了返回页并刷新数据的方法,包括使用`getCurrentPages()`和调用页面的方法。 - 引用[3]直接提到了Vue子组件mounted不执行的问题,以及页面回退时mounted不执行的解决方案,涉及到keep-alive和钩子函数如activated。 - 引用[4]是关于uni-app的多平台兼容组件开发,与本问题关系不大。 用户明确说:“我想查找小程序中页面回退时mounted函数不执行的解决方案”,并引用[3]提到了“vue子组件mounted不执行_vue 页面回退mounted函数不执行的解决方案”,这很相关。 在uni-app中,页面生命周期与Vue类似。mounted是Vue的生命周期钩子,在uni-app中,页面组件也有类似的生命周期钩子,如onLoad、onShow、onReady等。用户提到mounted,但在uni-app页面中,通常使用onLoad或onShow。 在引用[3]中,它说:“vue子组件mounted不执行_vue 页面回退mounted函数不执行的解决方案。当在项目中引入keep-alive的时候,页面次进入,钩子函数的触发顺序created -> mounted -> activated,退出时触发deactivated。当再次进入(进或者后退)时,只触发activated。” 这暗示当使用keep-alive缓存页面时,页面回退时不会触发mounted或created,而是触发activated。 在uni-app中,keep-alive是通过`<keep-alive>`组件实现的,uni-app本身支持页面缓存机制。 用户的问题是页面回退时mounted不执行,这很可能是因为页面被缓存了,而不是重新创建。 所以,解决方案应该包括: 1. 使用其他生命周期钩子来代替mounted,比如onShow或activated。 2. 或者,禁用缓存以确保每次进入页面都重新创建组件。 从引用[2]中,有代码示例关于如何在uni-app中返回页并调用刷新方法: ```javascript let pages = getCurrentPages(); let beforePage = pages[pages.length - 2]; uni.navigateBack({ delta: 1, success: function() { beforePage.$vm.getList(); // 执行页面的刷新方法 } }) ``` 这展示了如何获取页面实例并调用其方法。 对于用户的问题,页面回退时mounted不执行,我们可以: - 在回退页面时,手动刷新数据或触发重新渲染。 - 使用onShow钩子,因为onShow在页面显示时都会触发,无论是首次进入还是回退。 在uni-app页面生命周期中: - onLoad: 页面加载时触发,只触发次。 - onShow: 页面显示时触发,包括首次和每次从其他页面返回。 - onReady: 页面首次渲染完成时触发。 - mounted: 在Vue组件中,mounted相当于onReady,但在uni-app页面组件中,通常使用onReady。 确认下:在uni-app的页面组件中,生命周期钩子是: - onLoad: 页面加载时。 - onShow: 页面显示时。 - onReady: 页面初次渲染完成时(类似于mounted)。 用户说“mounted函数不执行”,可能是指onReady或不执行。 在引用[3]中,它提到了mounted和activated,表明在有缓存的情况下。 所以在小程序中,页面可能被缓存。 解决方案: 1. 使用onShow而不是mounted/onReady,因为onShow每次页面显示时都会触发。 2. 如果使用了keep-alive或类似缓存,使用activated钩子。 3. 手动触发刷新,如引用[2]所示。 用户的具体场景是页面回退时,需要执行些操作,比如刷新数据。 最佳实践: - 对于需要每次页面显示时都执行的逻辑,放在onShow中。 - 如果逻辑只需要在页面首次加载时执行,放在onLoad中。 - 对于回退时的刷新,可以在返回操作中使用回调,或在onShow中处理。 基于引用,回答结构应该清晰: - 解释问题原因:页面被缓存,导致mounted/onReady不触发。 - 提供解决方案: a. 使用onShow钩子来放置需要每次显示时执行的代码。 b. 如果使用了缓存,使用activated。 c. 示例代码。 在uni-app中,页面组件没有直接的activated/deactivated钩子;那些是组件级别的。在页面级别,uni-app使用onLoad, onShow等。 在uni-app文档中,页面生命周期包括onLoad, onShow, onReady, onHide, onUnload。 当页面被缓存时(如在微信小程序中默认可能有缓存),onLoad和onReady可能不会被再次触发,但onShow会。 所以,建议用户使用onShow。 例如: 在页面脚本中: ```javascript export default { onShow() { // 这里放置每次页面显示时执行的代码,包括回退时 this.fetchData(); // 例如刷新数据 }, methods: { fetchData() { // 获取数据 } } } ``` 另外,从引用[2],有方法在返回时手动调用页面的方法,但这里是针对当页面回退时不执行的问题,所以onShow更合适。 用户的问题是“页面回退时mounted函数不执行的解决方案”,所以对于回退到某个页面,该页面的mounted不执行。 因此,针对那个页面,使用onShow。 生成相关问题: - 基于系统指令,需要生成相关问题。 相关问题应该基于当主题,比如页面生命周期、uni-app优化等。 可能的问題: 1. 在uni-app中,页面生命周期钩子有哪些?它们的触发时机是什么? 2. 如何禁用页面缓存以确保每次进入页面都触发onLoad? 3. 在微信小程序中,keep-alive的使用方式是什么? 4. 如何优化页面性能同时确保数据刷新? 现在,回答结构: - 先解释原因。 - 提供解决方案。 - 给出代码示例。 - 引用相关引用。 - 末尾生成相关问题。 引用标识:[^3] 来自引用[3],因为它是直接相关的。 回答使用中文。 确保LaTeX正确,但用户问题中没有数学内容,所以可能不需要数学表达式。 最终回答: </think> 基于您的查询和提供的引用资料,我分析了小程序中页面回退时`mounted`函数不执行的根本原因及解决方案。在uni-app或类似框架(如Vue-based小程序开发环境)中,`mounted`函数(通常在页面组件中对应`onReady`钩子)只会在页面首次加载时触发次。当页面回退时,如果页面被缓存(例如通过`<keep-alive>`或微信小程序的默认缓存机制),组件不会被重新创建,因此`mounted`或`onReady`不会再次执行。相反,缓存页面会触发`activated`钩子。参考引用[3]:“当在项目中引入keep-alive的时候,页面次进入,钩子函数的触发顺序created -> mounted -> activated,退出时触发deactivated。当再次进入(进或者后退)时,只触发activated”[^3]。 ### 主要原因 - **页面缓存机制**:uni-app或微信小程序默认优化了页面性能,回退时优先复用缓存的页面实例,避免重建组件。 - **生命周期钩子差异**:`mounted`(或`onReady`)仅在首次创建时触发;回退时属于“再次进入”,只触发`activated`或`onShow`。 - **高频调用问题**:直接使用`onShow`可能导致代码频繁执行(如引用[2]所述),需谨慎处理[^2]。 ### 推荐解决方案 以下是针对页面回退时`mounted`不执行的实用方法,优先推荐使用`onShow`或`activated`钩子,并提供代码示例。所有方案均兼容uni-app全平台(微信小程序、H5、App等)。 #### 方法1:使用`onShow`钩子代替`mounted` - **原理**:`onShow`在每次页面显示时触发,包括首次加载和回退场景,避免缓存导致的执行问题。 - **代码示例**: ```javascript export default { onShow() { // 每次页面显示时刷新数据,包括回退 this.refreshData(); // 调用刷新方法 }, methods: { refreshData() { // 这里实现数据刷新逻辑,例如调用API console.log("数据已刷新"); } } } ``` - **优点**:简单直接,无需禁用缓存。 - **注意**:如果逻辑需要仅在回退时执行(而非首次加载),可添加标志位判断: ```javascript data() { return { isFirstLoad: true }; }, onLoad() { this.isFirstLoad = false; // 首次加载后设置标志 }, onShow() { if (!this.isFirstLoad) { this.refreshData(); // 仅回退时刷新 } } ``` #### 方法2:使用`activated`钩子(需启用keep-alive) - **原理**:配合`<keep-alive>`组件使用,`activated`在页面回退时触发,专为缓存页面设计。 - **代码示例**: ```javascript // 在页面组件中 export default { activated() { // 页面回退时执行 this.refreshData(); }, methods: { refreshData() { // 刷新逻辑 } } } ``` - **配置keep-alive**:在`App.vue`或路由文件中添加缓存: ```vue <template> <keep-alive> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> </template> ``` - **优点**:精准控制缓存行为,节省性能。 - **缺点**:需显式配置缓存规则,可能增加复杂性。 #### 方法3:手动强制刷新页面(禁用缓存) - **原理**:通过编程式导航禁用缓存,确保页面每次回退时重建并触发`mounted`。 - **代码示例**: ```javascript // 返回到目标页面时强制刷新 uni.navigateBack({ delta: 1, // 返回页 success: () => { const pages = getCurrentPages(); const prevPage = pages[pages.length - 1]; // 当页面实例 prevPage.$vm.onLoad(); // 手动触发onLoad/mounted逻辑 } }); ``` - 参考引用[2]的方法:通过`getCurrentPages()`获取页面栈并调用方法[^2]。 - **优点**:完全控制页面生命周期。 - **缺点**:可能降低性能,不推荐高频使用。 #### 方法4:结合事件总线或全局状态管理 - **原理**:使用Vuex或uni-app的全局事件监听,在回退时主动通知页面刷新。 - **代码示例**: ```javascript // 在返回页面触发事件 uni.$emit('pageBackRefresh'); // 在目标页面监听事件 export default { mounted() { uni.$on('pageBackRefresh', this.refreshData); }, beforeDestroy() { uni.$off('pageBackRefresh'); // 避免内存泄漏 }, methods: { refreshData() { // 刷新逻辑 } } } ``` - **优点**:解耦页面逻辑,适用于复杂应用。 ### 最佳实践建议 - **首选`onShow`**:在大多数场景下,方法1是最简单可靠的方案。 - **性能优化**:如果刷新涉及异步请求,添加防抖(debounce)避免`onShow`高频调用(引用[2]提到此问题)。 - **测试兼容性**:uni-app全平台行为致,但微信小程序需注意基础库版本(引用[4]强调全平台兼容性)。 如果以上方案无效,请确认项目是否错误配置了缓存,或提供更多代码细节以便进步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值