UNPKG

wx-mini-weview

Version:

weixin UI

262 lines (233 loc) 8.36 kB
/** * 顶部导航栏组件 * * 【返回导航规则详解】 * ------------------------------------------------------ * doBack 方法处理逻辑: * * 1. backUrl 和 backOpenType 参数组合情况: * - backUrl 为空,backOpenType 任意值: * • 尝试使用 wx.navigateBack 返回上一页 * • 如果页面栈中只有一个页面(无法返回),则跳转到首页(homePage) * * - backUrl 有值,backOpenType 为 'navigateBack': * • 在页面栈中查找是否存在匹配 backUrl 的页面 * • 如果找到,计算 delta 并调用 wx.navigateBack 返回到该页面 * • 如果未找到,使用 wx.reLaunch 跳转到指定页面,避免导航断层 * * - backUrl 有值,backOpenType 为 'navigate': * • 使用 wx.navigateTo 保留当前页面并跳转 * * - backUrl 有值,backOpenType 为 'redirect': * • 使用 wx.redirectTo 关闭当前页面并跳转 * * - backUrl 有值,backOpenType 为 'reLaunch': * • 使用 wx.reLaunch 关闭所有页面并跳转 * * - backUrl 有值,backOpenType 为空或非法值: * • 默认使用 wx.redirectTo,在不增加页面栈深度的同时跳转 * * 2. 页面匹配规则: * - 当 backUrl 包含查询参数时,会将 URL 分为 path 和 query 两部分 * - 页面栈匹配时只比较 path 部分,忽略查询参数 * - 跳转时会保留原始的查询参数 * * 3. 首页处理: * - 组件提供 homePage 属性用于指定首页路径 * - 默认首页为 '/pages/yuenote/footprint/footprint' */ Component({ options: { styleIsolation: 'apply-shared' }, properties: { title: { type: String, value: '导航栏', }, backBtn: { type: Boolean, value: true }, backUrl: { type: String, value: '' }, backText: { type: String, value: '' }, backOpenType: { type: String, // 'navigate', 'redirect', 'reLaunch', 'navigateBack' value: 'navigateBack' }, homeUrl: { type: String, value: '/pages/yuenote/index/index' }, navHeight: { type: Number, value: 44 }, backIcon: { type: String, value: 'bi-chevron-left' }, homeIcon: { type: String, value: 'bi-house' }, useHomeIconOnHomePage: { type: Boolean, value: true }, hideBackBtnOnHomePage: { type: Boolean, value: true } }, data: { statusBarHeight: 0, totalHeight: 44, backApplyIcon: 'bi-chevron-left', isHomePage: false }, lifetimes: { attached() { try { const systemInfo = wx.getSystemInfoSync(); const statusBarHeight = systemInfo.statusBarHeight; const totalHeight = statusBarHeight + this.properties.navHeight; const homeUrl = this._normalizeUrl(this.properties.homeUrl); const pages = getCurrentPages(); const currentPage = pages.length > 0 ? this._normalizeUrl(pages[pages.length-1].route) : ''; const isHomePage = currentPage === homeUrl; this.setData({ statusBarHeight: statusBarHeight, totalHeight: totalHeight, backApplyIcon: this.properties.backIcon, isHomePage: isHomePage }); // 如果当前页面是首页且配置要使用首页图标,则设置首页图标 if (isHomePage && this.properties.useHomeIconOnHomePage) { this.setData({ backApplyIcon: this.properties.homeIcon }); } } catch (e) { console.error('Failed to get system info:', e); } } }, methods: { _normalizeUrl(url) { if (!url) return ''; return url.startsWith('/') ? url : '/' + url; }, doBack: function() { const pages = getCurrentPages(); const pagesLen = pages.length; const homeUrl = this._normalizeUrl(this.properties.homeUrl); const currentPage = pagesLen > 0 ? this._normalizeUrl(pages[pagesLen-1].route) : 'unknown'; console.log('[TopNav] 当前页面:', currentPage, '页面栈深度:', pagesLen, 'backUrl:', this.properties.backUrl || '空', 'backOpenType:', this.properties.backOpenType); // 检查是否需要更改图标 let goingToHomePage = false; if (!this.properties.backUrl) { if (pagesLen <= 1) { console.log('[TopNav] 原因:页面栈为空且无backUrl 方法:reLaunch 目标:', homeUrl); goingToHomePage = true; wx.reLaunch({ url: homeUrl }); } else { const prevPage = pagesLen > 1 ? this._normalizeUrl(pages[pagesLen-2].route) : '未知'; console.log('[TopNav] 原因:无backUrl且有上一页 方法:navigateBack 返回页面:', prevPage); // 判断返回后是否到首页 goingToHomePage = prevPage === homeUrl; wx.navigateBack({ delta: 1 }); } } else { // 标准化 backUrl let backUrl = this._normalizeUrl(this.properties.backUrl); goingToHomePage = backUrl === homeUrl; let path = backUrl; let query = ''; if (backUrl.includes('?')) { const urlParts = backUrl.split('?'); path = urlParts[0]; query = '?' + urlParts[1]; // 再次检查是否回到首页(不含参数) goingToHomePage = path === homeUrl; } switch (this.properties.backOpenType) { case 'navigateBack': let targetIndex = -1; for (let i = 0; i < pagesLen; i++) { const page = pages[i]; const pagePath = this._normalizeUrl(page.route); if (pagePath === path) { targetIndex = i; break; } } if (targetIndex >= 0) { const delta = pagesLen - 1 - targetIndex; console.log('[TopNav] 原因:页面栈中找到匹配页面 方法:navigateBack delta:', delta, '目标:', path); wx.navigateBack({ delta: delta }); } else { console.log('[TopNav] 原因:指定了backUrl但页面栈中无匹配 方法:reLaunch 目标:', backUrl); wx.reLaunch({ url: backUrl }); } break; case 'navigate': console.log('[TopNav] 原因:指定了navigate方式 方法:navigateTo 目标:', backUrl); wx.navigateTo({ url: backUrl, fail: (err) => console.error('[TopNav] navigateTo失败:', err) }); break; case 'redirect': console.log('[TopNav] 原因:指定了redirect方式 方法:redirectTo 目标:', backUrl); wx.redirectTo({ url: backUrl, fail: (err) => console.error('[TopNav] redirectTo失败:', err) }); break; case 'reLaunch': console.log('[TopNav] 原因:指定了reLaunch方式 方法:reLaunch 目标:', backUrl); wx.reLaunch({ url: backUrl, fail: (err) => console.error('[TopNav] reLaunch失败:', err) }); break; default: console.log('[TopNav] 原因:未指定有效openType 方法:redirectTo(默认) 目标:', backUrl); wx.redirectTo({ url: backUrl, fail: (err) => console.error('[TopNav] redirectTo失败:', err) }); break; } } // 如果配置了使用首页图标且导航目标是首页,更新图标 if (goingToHomePage && this.properties.useHomeIconOnHomePage) { this.setData({ backApplyIcon: this.properties.homeIcon }); } else { this.setData({ backApplyIcon: this.properties.backIcon }); } }, getTotalNavHeight: function() { return this.data.totalHeight; }, getStatusBarHeight: function() { return this.data.statusBarHeight; }, getNacvHeight: function() { return this.properties.navHeight; } } })