|
|
@@ -21,6 +21,9 @@ const TABBAR_API_NAMES = [
|
|
21
|
21
|
'setTabBarMidButton'
|
|
22
|
22
|
]
|
|
23
|
23
|
|
|
|
24
|
+/** 首次安装时缓存的原始 API(避免重复 bind 已包装函数) */
|
|
|
25
|
+const TABBAR_RAW_APIS = {}
|
|
|
26
|
+
|
|
24
|
27
|
let tabBarEntryTask = null
|
|
25
|
28
|
|
|
26
|
29
|
function readUniTabPagePaths() {
|
|
|
@@ -105,15 +108,16 @@ export function isTabBarRoute(route) {
|
|
105
|
108
|
}
|
|
106
|
109
|
|
|
107
|
110
|
/**
|
|
108
|
|
- * 当前栈顶是否为原生 TabBar 页(须 meta.isTabBar,不能只看 route)
|
|
109
|
|
- * H5 history 直开 /bqH5/pages/home/index 时 route 会匹配 Tab,但 meta.isTabBar 为 false
|
|
|
111
|
+ * 当前栈顶是否为原生 TabBar 页
|
|
|
112
|
+ * 须同时满足:meta.isTabBar === true 且 route 在 tabBar.list 内
|
|
|
113
|
+ * (仅 meta 或仅 route 在 H5 生产环境都可能误判,导致 setTabBarStyle:fail)
|
|
110
|
114
|
*/
|
|
111
|
115
|
export function isTabBarPage() {
|
|
112
|
|
- const meta = getCurrentPageMeta()
|
|
113
|
|
- if (meta && typeof meta.isTabBar === 'boolean') {
|
|
114
|
|
- return meta.isTabBar
|
|
|
116
|
+ if (!isTabBarRoute()) {
|
|
|
117
|
+ return false
|
|
115
|
118
|
}
|
|
116
|
|
- return false
|
|
|
119
|
+ const meta = getCurrentPageMeta()
|
|
|
120
|
+ return !!(meta && meta.isTabBar === true)
|
|
117
|
121
|
}
|
|
118
|
122
|
|
|
119
|
123
|
/**
|
|
|
@@ -162,18 +166,33 @@ function isTabBarFailMsg(msg) {
|
|
162
|
166
|
return String(msg || '').includes('TabBar') && String(msg || '').includes('fail')
|
|
163
|
167
|
}
|
|
164
|
168
|
|
|
|
169
|
+function rememberRawTabBarApi(target, name) {
|
|
|
170
|
+ if (TABBAR_RAW_APIS[name]) {
|
|
|
171
|
+ return TABBAR_RAW_APIS[name]
|
|
|
172
|
+ }
|
|
|
173
|
+ const fn = target[name]
|
|
|
174
|
+ if (typeof fn !== 'function') {
|
|
|
175
|
+ return null
|
|
|
176
|
+ }
|
|
|
177
|
+ if (fn._tabBarGuardRaw) {
|
|
|
178
|
+ TABBAR_RAW_APIS[name] = fn._tabBarGuardRaw
|
|
|
179
|
+ return TABBAR_RAW_APIS[name]
|
|
|
180
|
+ }
|
|
|
181
|
+ TABBAR_RAW_APIS[name] = fn.bind(target)
|
|
|
182
|
+ return TABBAR_RAW_APIS[name]
|
|
|
183
|
+}
|
|
|
184
|
+
|
|
165
|
185
|
/**
|
|
166
|
|
- * H5 生产包中 addInterceptor 偶发拦不住框架内部调用,直接包装 uni/wx API 更稳
|
|
|
186
|
+ * H5 生产包中框架 / uview 可能在我们安装守卫后又写回 uni API,故每次启动 / 切页都重装
|
|
167
|
187
|
*/
|
|
168
|
188
|
function wrapTabBarApi(target, name) {
|
|
169
|
189
|
if (!target || typeof target[name] !== 'function') {
|
|
170
|
190
|
return
|
|
171
|
191
|
}
|
|
172
|
|
- const current = target[name]
|
|
173
|
|
- if (current._tabBarGuardPatched) {
|
|
|
192
|
+ const raw = rememberRawTabBarApi(target, name)
|
|
|
193
|
+ if (!raw) {
|
|
174
|
194
|
return
|
|
175
|
195
|
}
|
|
176
|
|
- const raw = current.bind(target)
|
|
177
|
196
|
function patchedTabBarApi(options) {
|
|
178
|
197
|
const opts = options || {}
|
|
179
|
198
|
if (!isTabBarPage()) {
|
|
|
@@ -189,6 +208,22 @@ function wrapTabBarApi(target, name) {
|
|
189
|
208
|
throw err
|
|
190
|
209
|
})
|
|
191
|
210
|
}
|
|
|
211
|
+ if (ret && typeof ret.then === 'function') {
|
|
|
212
|
+ return ret.then(
|
|
|
213
|
+ (res) => {
|
|
|
214
|
+ if (res && isTabBarFailMsg(res.errMsg)) {
|
|
|
215
|
+ return noopTabBarResult(name)
|
|
|
216
|
+ }
|
|
|
217
|
+ return res
|
|
|
218
|
+ },
|
|
|
219
|
+ (err) => {
|
|
|
220
|
+ if (isTabBarFailMsg(err && err.errMsg)) {
|
|
|
221
|
+ return noopTabBarResult(name)
|
|
|
222
|
+ }
|
|
|
223
|
+ throw err
|
|
|
224
|
+ }
|
|
|
225
|
+ )
|
|
|
226
|
+ }
|
|
192
|
227
|
return ret
|
|
193
|
228
|
} catch (err) {
|
|
194
|
229
|
if (isTabBarFailMsg(err && err.errMsg)) {
|
|
|
@@ -198,6 +233,7 @@ function wrapTabBarApi(target, name) {
|
|
198
|
233
|
}
|
|
199
|
234
|
}
|
|
200
|
235
|
patchedTabBarApi._tabBarGuardPatched = true
|
|
|
236
|
+ patchedTabBarApi._tabBarGuardRaw = raw
|
|
201
|
237
|
target[name] = patchedTabBarApi
|
|
202
|
238
|
}
|
|
203
|
239
|
|