@tarojsx/ui
Version:
We reinvents the UI for Taro3+
132 lines • 5.63 kB
JavaScript
import { __rest } from "tslib";
import { useMemo, useState, useCallback, useEffect } from 'react';
import Taro, { eventCenter } from '@tarojs/taro';
import history from '@tarojsx/history';
import { uuid } from './utils';
let taroTabBarAPIPatched = false;
/** 将 Taro TabBar 相关 API 替换为触发事件, 启用自定义 TabBar 以后原 API 会报错, 所以此处直接覆盖. */
const taroTabBarAPIPatcher = () => {
if (taroTabBarAPIPatched)
return;
for (const api of [
'hideTabBar',
'showTabBar',
'setTabBarStyle',
'setTabBarItem',
'setTabBarBadge',
'removeTabBarBadge',
'showTabBarRedDot',
'hideTabBarRedDot',
]) {
Taro[api] = (params) => eventCenter.trigger('atCustomTabBar', api, params);
}
taroTabBarAPIPatched = true;
};
/**
* 默认选中值
*
* 当无法从路由信息中获取值的时候, 以默认值为准, 默认值在切换 Tab 时进行修改, 以实现新初始化的 TabBar 显示正确的选中项.
*/
let defaultCurrentIndex = -1;
/**
* 自定义 TabBar Render Props 组件, 提供用于渲染自定义 TabBar 所需的属性.
*
* 支持 API:
* * `Taro.hideTabBar()`
* * `Taro.showTabBar()`
*
* @since 2.5.0 微信开发者工具调试基础库 >= 2.5.2
*/
export const CustomTabBar = (props) => {
var _a;
const { children, appTabBarConfig = (_a = window.__taroAppConfig) === null || _a === void 0 ? void 0 : _a.tabBar } = props;
const { custom, list } = appTabBarConfig, defaultTabBarStyle = __rest(appTabBarConfig, ["custom", "list"]);
const [hidden, setHidden] = useState(false);
/**
* 根据路由推断 current index.
* 当前版本 taro 3.0.0.alpha.9 在程序启动时返回 router, 之后总是返回 null.
*/
const routerIndex = useMemo(() => list.findIndex((item) => { var _a; return (_a = Taro.Current.router) === null || _a === void 0 ? void 0 : _a.path.startsWith(item.pagePath); }), []);
const [current, setCurrent] = useState(~routerIndex ? routerIndex : defaultCurrentIndex);
const [tabBarStyle, setTabBarStyle] = useState(defaultTabBarStyle);
const [tabBarList, setTabBarList] = useState(list.map((item) => (Object.assign(Object.assign({}, item), { key: uuid(), pagePath: '/' + item.pagePath, iconPath: '/' + item.iconPath, selectedIconPath: item.selectedIconPath ? '/' + item.selectedIconPath : undefined, badge: '', redDot: false }))));
/**
* 更新指定位置的 Tab 配置
*/
const updateTabBarListAt = useCallback((tabIndex, params) => {
setTabBarList((prev) => prev.map((item, index) => (index === tabIndex ? Object.assign(Object.assign({}, item), params) : item)));
}, [setTabBarList]);
/**
* 用户点击 Tab
*
* 1. 记录全局索引, 如果下一个 Tab 是初次访问, 并且没能从路由中推断出索引, 则使用全局索引.
* 2. 触发事件, 通知所有已经初始化的自定义 TabBar 更新索引.
* 3. 切换 Tab 页面.
*/
const switchTabIndex = useCallback((index) => {
if (index >= 0 && index < tabBarList.length) {
defaultCurrentIndex = index;
eventCenter.trigger('atCustomTabBar', 'switchTabIndex', { index });
Taro.switchTab({ url: tabBarList[index].pagePath });
}
}, [tabBarList]);
/**
* 监听 history 修正当前 Tab 索引
*
* @since taro 3.0.0-rc.1
*/
useEffect(() => history.listen((location) => {
const tabBarPagePaths = appTabBarConfig.list.map((item) => '/' + item.pagePath);
const index = tabBarPagePaths.indexOf(location.path);
if (index >= 0 && index < tabBarPagePaths.length) {
defaultCurrentIndex = index;
setCurrent(index);
}
}), [appTabBarConfig]);
useEffect(() => {
// console.log('CustomTabBar mounted')
taroTabBarAPIPatcher();
/** 处理打过补丁后的 Taro API 传过来的事件. */
const handler = (api, _a = {}) => {
var { index } = _a, params = __rest(_a, ["index"]);
switch (api) {
case 'switchTabIndex':
setCurrent(index);
break;
case 'hideTabBar':
setHidden(true);
break;
case 'showTabBar':
setHidden(false);
break;
case 'setTabBarStyle':
setTabBarStyle(params);
break;
case 'setTabBarItem':
updateTabBarListAt(index, params);
break;
case 'setTabBarBadge':
updateTabBarListAt(index, { badge: params.text });
break;
case 'removeTabBarBadge':
updateTabBarListAt(index, { badge: '' });
break;
case 'showTabBarRedDot':
updateTabBarListAt(index, { redDot: true });
break;
case 'hideTabBarRedDot':
updateTabBarListAt(index, { redDot: false });
break;
default:
break;
}
};
eventCenter.on('atCustomTabBar', handler);
return () => {
// console.log('CustomTabBar unmounted')
eventCenter.off('atCustomTabBar', handler);
};
}, []);
return children ? children({ hidden, current, style: tabBarStyle, list: tabBarList, switchTabIndex }) : null;
};
//# sourceMappingURL=CustomTabBar.js.map