✨点击上方关注☝️,追踪不迷路!
前言
"大家要是使用过京东的taro框架,都知道taro1.x是支持生命周期BeforeRouteLeave的,这个生命周期主要是用来监听用户返回页面或前进操作,用于弹出弹窗挽留用户等,那么假如你升级到了taro3或taro4,官方是不支持这个生命周期的,需要自己实现,本文主要就是介绍如何添加实现这个功能"

hook接口设计
接口名称
useBeforeRouteLeave(fn)
自定义 React 钩子,用于在 Taro 应用中拦截路由跳转,并在跳转前执行自定义逻辑(例如提示用户挽留)
使用场景
- 在用户尝试离开当前页面时,提示挽留等。
- 在特定条件下阻止路由跳转。
入参说明
参数 | 类型 | 是否必须 | 描述 |
---|---|---|---|
fn | Fuction | 是 | 拦截逻辑回调函数,接收一个对象参数{ from, to, next }。 |
fn回调参数说明
参数 | 类型 | 是否必须 | 描述 |
---|---|---|---|
from | String | 当前路由路径 | |
to | String | 目标路由路径 | |
next | String | 控制是否允许跳转的函数。flag=true允许跳转,flag=false阻止跳转。 |
返回值
无返回值
示例代码
js
import useBeforeRouteLeave from './hooks/useBeforeRouteLeave';
function MyComponent() {
useBeforeRouteLeave(({ from, to, next }) => {
Taro.showModal({
title: '是否离开?',
confirmText: "确定"
}).then(res=>{
if (res.confirm) {
next(true)
} else {
next(false)
}
})
});
return <div>My Component</div>;
}
代码逻辑设计

代码实现设计
js
import { useEffect } from 'react'
import { useDidShow } from '@tarojs/taro'
import { history } from '@tarojs/router'
export default function useBeforeRouteLeave(fn) {
let isunBlocked = false; // 标记拦截状态
const from = history.location.pathname;
const unblockWrap = () => {
let unblock = history.block((tx) => {
let to = tx.location.pathname
const next = (flag) => {
if (flag) {
setTimeout(() => {
unblock() // 解除拦截
tx.retry() // 重试跳转
isunBlocked = true; // 更新拦截状态
})
}
}
fn({ from, to, next })
})
return () => unblock(); // 返回清理函数
}
useEffect(() => { // 注册拦截
return unblockWrap()
})
useDidShow(() => {
if(isunBlocked) {
isunBlocked = false;
unblockWrap() // 重新启用拦截
}
})
}
- 初始化拦截状态:isunBlocked 标记拦截状态,默认为false。
- 注册拦截逻辑:通过history.block拦截路由跳转。
- 执行回调:当拦截触发时,调用用户传入的fn函数。
- 用户决策:用户通过next(flag)决定是否允许跳转。
- 如果flag=true,解除拦截并重试跳转。
- 如果flag=false,保持拦截状态。
- 重新启用拦截:当页面重新显示时(useDidShow),重置拦截状态并重新注册拦截逻辑。
装饰器接口设计
接口名称
useBeforeRouteLeaveHoc()
自定义 React 高阶组件,用于在 Taro 应用中拦截路由跳转,并在跳转前执行自定义逻辑(例如提示挽留)
使用场景
- 在用户尝试离开当前页面时,提示挽留等。
- 在特定条件下阻止路由跳转。
装饰说明
给 class 类组件注入了生命周期beforeRouteLeave({from, to, next})
反参说明
参数 | 类型 | 是否必须 | 描述 |
---|---|---|---|
from | String | 当前路由路径 | |
to | String | 目标路由路径 | |
next | String | 控制是否允许跳转的函数。flag=true允许跳转,flag=false阻止跳转。 |
示例代码
js
import { Component } from 'react';
import Taro from "@tarojs/taro";
import { Button, View } from "@tarojs/components";
import { beforeRouteLeaveHoc } from '../../hoc/index';
@beforeRouteLeaveHoc()
class MyComponent extends Component {
beforeRouteLeave({from, to, next}) {
console.log('wen', 'beforeRouteLeave');
Taro.showModal({
title: 'beforeRouteLeave确定离开吗'
}).then((res) => {
if (res.confirm) {
next(true);
}
if (res.cancel) {
next(false);
}
});
}
handleRoute = () => {
Taro.navigateTo({
url: '/pages/index/index'
})
}
render() {
return (<View>
<Button onClick={this.handleRoute.bind(this)}>跳转首页</Button>
</View>)
}
}
export default MyComponent;
代码逻辑设计
和hook方式代码逻辑设计一样
代码实现设计
js
import { history } from '@tarojs/router';
/**
* 路由离开拦截装饰器
*/
export function beforeRouteLeaveHoc() {
return function (constructor) {
return class extends constructor {
constructor(...args) {
super(...args);
this.isunBlocked = false; // 拦截状态标记
this.from = history.location.pathname; // 当前路径
this.unblock = null; // 拦截器清理函数
}
componentDidMount() {
if (super.componentDidMount) super.componentDidMount();
this.setupRouteInterceptor();
}
componentDidShow() {
if (super.componentDidShow) super.componentDidShow();
if (this.isunBlocked) {
this.isunBlocked = false;
this.setupRouteInterceptor();
}
}
componentWillUnmount() {
if (super.componentWillUnmount) super.componentWillUnmount();
if (this.unblock) this.unblock();
}
setupRouteInterceptor() {
this.unblock = history.block((tx) => {
const to = tx.location.pathname;
const next = (flag) => {
if (flag) {
setTimeout(() => {
if (this.unblock) this.unblock(); // 解除拦截
tx.retry(); // 重试跳转
this.isunBlocked = true; // 更新拦截状态
});
}
};
super.beforeRouteLeave && super.beforeRouteLeave({ from: this.from, to, next });
});
}
};
};
}
最后,创作不易请允许我插播一则自己开发的小程序广告,感兴趣可以访问体验:
【「合图图」产品介绍】
-
主要功能为:本地添加相册图片进行无限长图高清拼接,各种布局拼接等
-
安全:无后台服务无需登录,全程设备本地运行,隐私100%安全;
-
高效:自由布局+实时预览,效果所见即所得;
-
高清:秒生高清拼图,一键保存相册。
-
立即体验 →合图图 或微信小程序搜索「合图图」
如果觉得本文有用 ,欢迎点个赞👍和收藏⭐支持我吧!