HarmonyOS7 底部 Tab 数据模型拆解:TabsBarModel 为什么要单独写
·
MainPage.ets 里没有把四个 tab 写死在页面里,而是抽到了 TabsBarModel.ets。这个小设计很值得学,因为它让页面代码清爽很多。
项目源码:https://gitcode.com/HarmonyOS_Samples/SmartReach/tree/master
页面里只拿结果
主页面只写了这一句:
private tabsBar: BottomTabBarStyle[] = TabsBarModel.getTabBarByPage() ?? [];
然后在 HdsTabs 里循环:
Repeat(this.tabsBar).each((repeatItem: RepeatItem<BottomTabBarStyle>) => {
TabContent() {
WaterFlowView({
currentTabIndex: repeatItem.index,
})
}
.tabBar(repeatItem.item)
})
页面不关心图标怎么生成,也不关心选中态颜色怎么配。它只管拿到 BottomTabBarStyle[] 并渲染。
BAR_ITEMS 是原始配置
TabsBarModel.ets 里先定义了四个 tab:
const BAR_ITEMS: BarItem[] = [
{
label: $r('app.string.tab_home'),
normalColor: $r('sys.color.icon_primary'),
normalSymbolResource: $r('sys.symbol.house_fill'),
selectedColor: $r('sys.color.icon_emphasize'),
selectedSymbolResource: $r('sys.symbol.house_fill'),
},
{
label: $r('app.string.tab_video'),
normalColor: $r('sys.color.icon_primary'),
normalSymbolResource: $r('sys.symbol.play_hexagon_fill'),
selectedColor: $r('sys.color.icon_emphasize'),
selectedSymbolResource: $r('sys.symbol.play_hexagon_fill'),
}
]

真实文件里有四项:首页、视频、购物、我的。这里为了阅读只截两项。
SymbolGlyphModifier 负责图标样式
生成 tab 样式的核心代码是:
const tabBarStyle = new BottomTabBarStyle({
normal: new SymbolGlyphModifier(item.normalSymbolResource)
.renderingStrategy(SymbolRenderingStrategy.SINGLE)
.fontColor([item.normalColor]),
selected: new SymbolGlyphModifier(item.selectedSymbolResource)
.renderingStrategy(SymbolRenderingStrategy.SINGLE)
.fontColor([item.selectedColor])
}, item.label)
.labelStyle({
unselectedColor: item.normalColor,
selectedColor: item.selectedColor,
});
这段代码做了两套样式:普通状态和选中状态。图标用系统 symbol,颜色也用系统颜色资源。
为什么要缓存
TabsBarModel 里有一个缓存:
private static cachedTabBarStyleList?: BottomTabBarStyle[];
public static getTabBarByPage(): BottomTabBarStyle[] {
if (!TabsBarModel.cachedTabBarStyleList) {
const tabBarStyleList: BottomTabBarStyle[] = [];
// 生成 BottomTabBarStyle
TabsBarModel.cachedTabBarStyleList = tabBarStyleList;
}
return TabsBarModel.cachedTabBarStyleList;
}
这个缓存不是必须,但挺合理。Tab 样式通常不会频繁变化,生成一次复用就够了。
SCROLLER_LIST 也放在这里
文件最后还有:
export const SCROLLER_LIST: Scroller[] = new Array(4).fill(null).map(() => new Scroller());
每个 tab 对应一个 Scroller,后面 HdsNavigation 会绑定它:
.bindToScrollable(SCROLLER_LIST)
这样导航栏滚动效果和不同页签里的滚动区域就能关联起来。
写在最后
TabsBarModel 看起来只是个小文件,但它体现了一个很实用的思路:页面只负责渲染,配置和样式生成放到模型层。小项目这么写不麻烦,大项目这么写会救命。
更多推荐


所有评论(0)