refactor(nav): 动态控制导航栏返回按钮显示逻辑
1. 新增isTabBarRootPage工具方法判断是否为tab根页面 2. 在全局混入中添加isTabRootPage计算属性 3. 替换多处硬编码的isBack属性为动态绑定 4. 优化shouldShowTabBar计算属性的代码逻辑
This commit is contained in:
@@ -1,14 +1,68 @@
|
||||
// 内部 helper:获取当前页面实例
|
||||
const _getCurrentPage = () => {
|
||||
const pages = getCurrentPages();
|
||||
return pages.length === 0 ? null : pages[pages.length - 1];
|
||||
};
|
||||
|
||||
// 内部 helper:获取当前页面路由(统一提取 route 或 $page.path)
|
||||
const _getCurrentRoute = (currentPage) => {
|
||||
if (!currentPage) return '';
|
||||
if (currentPage.route) return currentPage.route;
|
||||
if (currentPage.$page && currentPage.$page.path) return currentPage.$page.path;
|
||||
return '';
|
||||
};
|
||||
|
||||
// 内部 helper:判断 tabBarList 是否已加载且有 list 配置
|
||||
const _isValidTabBarList = (tabBarList) => {
|
||||
return tabBarList && tabBarList.list;
|
||||
};
|
||||
|
||||
// 内部 helper:规范化路由:无前导斜杠时补全
|
||||
const _normalizeLeadingSlash = (route) => {
|
||||
if (!route) return route;
|
||||
return route.startsWith('/') ? route : '/' + route;
|
||||
};
|
||||
|
||||
// 内部 helper:通过 $util 方法的安全调用
|
||||
const _callUtil = (vm, method, ...args) => {
|
||||
if (vm.$util && vm.$util[method]) {
|
||||
return vm.$util[method](...args);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export default {
|
||||
onLoad() { },
|
||||
onShow() {
|
||||
// 刷新多语言
|
||||
this.$langConfig.refresh();
|
||||
|
||||
// TabBar 根页面时隐藏系统导航栏的返回按钮
|
||||
// (uni-app 的系统导航栏在通过 navigateTo 跳转到 tab 页时可能残留返回键)
|
||||
const tabBarList = this.$store.state.tabBarList;
|
||||
if (!_isValidTabBarList(tabBarList)) return;
|
||||
const currentRoute = _getCurrentRoute(_getCurrentPage());
|
||||
if (!currentRoute) return;
|
||||
const isRoot = _callUtil(this, 'isTabBarRootPage', currentRoute, tabBarList) || false;
|
||||
if (isRoot) {
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ || MP-ALIPAY
|
||||
try { uni.hideHomeButton(); } catch (e) { /* 兼容 */ }
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否是英文环境
|
||||
isEnEnv() {
|
||||
return this.$langConfig.getCurrentLocale() === 'en-us';
|
||||
},
|
||||
// 动态判断:当前页面是否是 TabBar 根页面(tab 根页不应显示返回按钮)
|
||||
isTabRootPage() {
|
||||
const tabBarList = this.$store.state.tabBarList;
|
||||
if (!_isValidTabBarList(tabBarList)) return false;
|
||||
const currentRoute = _getCurrentRoute(_getCurrentPage());
|
||||
if (!currentRoute) return false;
|
||||
return _callUtil(this, 'isTabBarRootPage', currentRoute, tabBarList) || false;
|
||||
},
|
||||
themeStyle() {
|
||||
return this.$store.state.themeStyle;
|
||||
},
|
||||
@@ -24,43 +78,18 @@ export default {
|
||||
},
|
||||
shouldShowTabBar() {
|
||||
const tabBarList = this.$store.state.tabBarList;
|
||||
if (!tabBarList || !tabBarList.list) {
|
||||
return false;
|
||||
}
|
||||
if (!_isValidTabBarList(tabBarList)) return false;
|
||||
const mode = tabBarList.page_visibility_mode;
|
||||
const routeList = tabBarList.page_routes || [];
|
||||
if (!mode || mode === 'all') {
|
||||
return true;
|
||||
}
|
||||
if (mode === 'none') {
|
||||
return false;
|
||||
}
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length === 0) {
|
||||
return true;
|
||||
}
|
||||
const currentPage = pages[pages.length - 1];
|
||||
let currentRoute = '';
|
||||
if (currentPage.route) {
|
||||
currentRoute = currentPage.route;
|
||||
} else if (currentPage.$page && currentPage.$page.path) {
|
||||
currentRoute = currentPage.$page.path;
|
||||
}
|
||||
if (!currentRoute) {
|
||||
return true;
|
||||
}
|
||||
if (!currentRoute.startsWith('/')) {
|
||||
currentRoute = '/' + currentRoute;
|
||||
}
|
||||
const inList = this.$util && this.$util.isPageInRouteList
|
||||
? this.$util.isPageInRouteList(currentRoute, routeList)
|
||||
: false;
|
||||
if (mode === 'whitelist') {
|
||||
return inList;
|
||||
}
|
||||
if (mode === 'blacklist') {
|
||||
return !inList;
|
||||
}
|
||||
if (!mode || mode === 'all') return true;
|
||||
if (mode === 'none') return false;
|
||||
const currentPage = _getCurrentPage();
|
||||
if (!currentPage) return true;
|
||||
const currentRoute = _normalizeLeadingSlash(_getCurrentRoute(currentPage));
|
||||
if (!currentRoute) return true;
|
||||
const inList = _callUtil(this, 'isPageInRouteList', currentRoute, routeList) || false;
|
||||
if (mode === 'whitelist') return inList;
|
||||
if (mode === 'blacklist') return !inList;
|
||||
return true;
|
||||
},
|
||||
tabBarPagePaddingStyle() {
|
||||
|
||||
@@ -341,6 +341,24 @@ function _findMatchingTabUrl(currentPagePath, tabBarList, packageEntryTab) {
|
||||
return tabUrls.find(url => _getPackageName(url) === packageName) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断给定路径是否是 TabBar 根页面(与 diy_bottom_nav 中任意一项精确相等)
|
||||
* @param {string} pagePath 当前页面路径(可以带/不带前导斜杠、可以带 query)
|
||||
* @param {Object|null} tabBarList tabBar 配置对象($store.state.tabBarList)
|
||||
* @returns {boolean} 如果是 TabBar 根页面返回 true;路径无效/未配置 tabBarList 时返回 false
|
||||
*/
|
||||
export const isTabBarRootPage = (pagePath, tabBarList) => {
|
||||
if (!pagePath) return false;
|
||||
if (!tabBarList || !tabBarList.list || !Array.isArray(tabBarList.list)) return false;
|
||||
const normalizedCurrent = _normalizePath(pagePath);
|
||||
if (!normalizedCurrent) return false;
|
||||
return tabBarList.list.some(item => {
|
||||
if (!item || !item.link || !item.link.wap_url) return false;
|
||||
const normalizedTab = _normalizePath(item.link.wap_url);
|
||||
return normalizedTab === normalizedCurrent;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查tabBar是否激活
|
||||
* @param {string} linkUrl 链接路径 /pages/goods/category
|
||||
@@ -404,6 +422,9 @@ export default {
|
||||
/** 解析 link 对象得到最终可跳转的 URL(优先级: page_key → wap_url) */
|
||||
resolveLinkUrl,
|
||||
|
||||
/** 判断给定路径是否是 TabBar 根页面(用于动态控制返回按钮显示) */
|
||||
isTabBarRootPage,
|
||||
|
||||
/**
|
||||
* 页面跳转
|
||||
* @param {string} to 跳转链接 /pages/idnex/index
|
||||
@@ -436,6 +457,33 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 动态 diy tabBar:如果目标是 diy_bottom_nav 中的 tab 根页
|
||||
// 注意:uni.switchTab 仅对 pages.json 中 tabBar.list 注册的页面有效,
|
||||
// 其他 DIY 配置页面调用 switchTab 会静默失败(点击无响应)。
|
||||
// 因此使用 uni.redirectTo 替换当前页:不进栈 → 无返回按钮 → 对任意页面都有效。
|
||||
const diyTabBar = store.state.tabBarList;
|
||||
if (diyTabBar && diyTabBar.list && Array.isArray(diyTabBar.list)) {
|
||||
const cleanUrl = url.split('?')[0];
|
||||
const isDiyTabRoot = diyTabBar.list.some(item => {
|
||||
if (!item || !item.link || !item.link.wap_url) return false;
|
||||
const normalizedTab = _normalizePath(item.link.wap_url);
|
||||
const normalizedUrl = _normalizePath(cleanUrl);
|
||||
return normalizedTab === normalizedUrl;
|
||||
});
|
||||
if (isDiyTabRoot) {
|
||||
const adaptedUrl = adaptSubpackageUrl(cleanUrl);
|
||||
const inSystemTabBar = systemTabBarList.some(sysUrl => adaptedUrl === sysUrl || cleanUrl === sysUrl);
|
||||
const navApi = inSystemTabBar ? uni.switchTab : uni.redirectTo;
|
||||
navApi({
|
||||
url,
|
||||
fail: (err) => {
|
||||
console.error('[navigate] tabBar 跳转失败:', cleanUrl, err);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 如果url不包含tabBarList中的路径,根据mode判断跳转方式
|
||||
switch (mode) {
|
||||
case 'tabbar':
|
||||
|
||||
Reference in New Issue
Block a user