TabBar 标签栏

位于 APP 底部,方便用户在不同功能模块之间进行快速切换。

规则

  • 用作 APP 的一级分类,数量控制在 3-5 个之间。

  • 即使某个 Tab 不可用,也不要禁用或者移除该 Tab。

  • 使用 Badge 进行提示,足不出户也能知道有内容更新。

代码演示

APP 型选项卡

多用于页面的内容区块,起着控制小范围内的大块内容的分组和隐藏,起着保持界面整洁的作用。

  1. import { TabBar } from 'antd-mobile';
  2. class TabBarExample extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. selectedTab: 'redTab',
  7. hidden: false,
  8. fullScreen: false,
  9. };
  10. }
  11. renderContent(pageText) {
  12. return (
  13. <div style={{ backgroundColor: 'white', height: '100%', textAlign: 'center' }}>
  14. <div style={{ paddingTop: 60 }}>Clicked “{pageText}” tab show “{pageText}” information</div>
  15. <a style={{ display: 'block', marginTop: 40, marginBottom: 20, color: '#108ee9' }}
  16. onClick={(e) => {
  17. e.preventDefault();
  18. this.setState({
  19. hidden: !this.state.hidden,
  20. });
  21. }}
  22. >
  23. Click to show/hide tab-bar
  24. </a>
  25. <a style={{ display: 'block', marginBottom: 600, color: '#108ee9' }}
  26. onClick={(e) => {
  27. e.preventDefault();
  28. this.setState({
  29. fullScreen: !this.state.fullScreen,
  30. });
  31. }}
  32. >
  33. Click to switch fullscreen
  34. </a>
  35. </div>
  36. );
  37. }
  38. render() {
  39. return (
  40. <div style={this.state.fullScreen ? { position: 'fixed', height: '100%', width: '100%', top: 0 } : { height: 400 }}>
  41. <TabBar
  42. unselectedTintColor="#949494"
  43. tintColor="#33A3F4"
  44. barTintColor="white"
  45. hidden={this.state.hidden}
  46. >
  47. <TabBar.Item
  48. title="Life"
  49. key="Life"
  50. icon={<div style={{
  51. width: '22px',
  52. height: '22px',
  53. background: 'url(https://zos.alipayobjects.com/rmsportal/sifuoDUQdAFKAVcFGROC.svg) center center / 21px 21px no-repeat' }}
  54. />
  55. }
  56. selectedIcon={<div style={{
  57. width: '22px',
  58. height: '22px',
  59. background: 'url(https://zos.alipayobjects.com/rmsportal/iSrlOTqrKddqbOmlvUfq.svg) center center / 21px 21px no-repeat' }}
  60. />
  61. }
  62. selected={this.state.selectedTab === 'blueTab'}
  63. badge={1}
  64. onPress={() => {
  65. this.setState({
  66. selectedTab: 'blueTab',
  67. });
  68. }}
  69. data-seed="logId"
  70. >
  71. {this.renderContent('Life')}
  72. </TabBar.Item>
  73. <TabBar.Item
  74. icon={
  75. <div style={{
  76. width: '22px',
  77. height: '22px',
  78. background: 'url(https://gw.alipayobjects.com/zos/rmsportal/BTSsmHkPsQSPTktcXyTV.svg) center center / 21px 21px no-repeat' }}
  79. />
  80. }
  81. selectedIcon={
  82. <div style={{
  83. width: '22px',
  84. height: '22px',
  85. background: 'url(https://gw.alipayobjects.com/zos/rmsportal/ekLecvKBnRazVLXbWOnE.svg) center center / 21px 21px no-repeat' }}
  86. />
  87. }
  88. title="Koubei"
  89. key="Koubei"
  90. badge={'new'}
  91. selected={this.state.selectedTab === 'redTab'}
  92. onPress={() => {
  93. this.setState({
  94. selectedTab: 'redTab',
  95. });
  96. }}
  97. data-seed="logId1"
  98. >
  99. {this.renderContent('Koubei')}
  100. </TabBar.Item>
  101. <TabBar.Item
  102. icon={
  103. <div style={{
  104. width: '22px',
  105. height: '22px',
  106. background: 'url(https://zos.alipayobjects.com/rmsportal/psUFoAMjkCcjqtUCNPxB.svg) center center / 21px 21px no-repeat' }}
  107. />
  108. }
  109. selectedIcon={
  110. <div style={{
  111. width: '22px',
  112. height: '22px',
  113. background: 'url(https://zos.alipayobjects.com/rmsportal/IIRLrXXrFAhXVdhMWgUI.svg) center center / 21px 21px no-repeat' }}
  114. />
  115. }
  116. title="Friend"
  117. key="Friend"
  118. dot
  119. selected={this.state.selectedTab === 'greenTab'}
  120. onPress={() => {
  121. this.setState({
  122. selectedTab: 'greenTab',
  123. });
  124. }}
  125. >
  126. {this.renderContent('Friend')}
  127. </TabBar.Item>
  128. <TabBar.Item
  129. icon={{ uri: 'https://zos.alipayobjects.com/rmsportal/asJMfBrNqpMMlVpeInPQ.svg' }}
  130. selectedIcon={{ uri: 'https://zos.alipayobjects.com/rmsportal/gjpzzcrPMkhfEqgbYvmN.svg' }}
  131. title="My"
  132. key="my"
  133. selected={this.state.selectedTab === 'yellowTab'}
  134. onPress={() => {
  135. this.setState({
  136. selectedTab: 'yellowTab',
  137. });
  138. }}
  139. >
  140. {this.renderContent('My')}
  141. </TabBar.Item>
  142. </TabBar>
  143. </div>
  144. );
  145. }
  146. }
  147. ReactDOM.render(<TabBarExample />, mountNode);
  1. #tab-bar.demo {
  2. display: flex;
  3. flex-direction: column;
  4. }
  5. #tab-bar .demoName {
  6. height: 40px;
  7. }
  8. #tab-bar .demo-preview-item .am-tab-bar {
  9. background-color: white;
  10. }

与ListView结合使用

  1. import { TabBar, ListView } from 'antd-mobile';
  2. const data = [
  3. {
  4. img: 'https://zos.alipayobjects.com/rmsportal/dKbkpPXKfvZzWCM.png',
  5. title: 'Meet hotel',
  6. des: '不是所有的兼职汪都需要风吹日晒',
  7. },
  8. {
  9. img: 'https://zos.alipayobjects.com/rmsportal/XmwCzSeJiqpkuMB.png',
  10. title: 'McDonald\'s invites you',
  11. des: '不是所有的兼职汪都需要风吹日晒',
  12. },
  13. {
  14. img: 'https://zos.alipayobjects.com/rmsportal/hfVtzEhPzTUewPm.png',
  15. title: 'Eat the week',
  16. des: '不是所有的兼职汪都需要风吹日晒',
  17. },
  18. ];
  19. const NUM_SECTIONS = 5;
  20. const NUM_ROWS_PER_SECTION = 5;
  21. let pageIndex = 0;
  22. const dataBlobs = {};
  23. let sectionIDs = [];
  24. let rowIDs = [];
  25. function genData(pIndex = 0) {
  26. for (let i = 0; i < NUM_SECTIONS; i++) {
  27. const ii = (pIndex * NUM_SECTIONS) + i;
  28. const sectionName = `Section ${ii}`;
  29. sectionIDs.push(sectionName);
  30. dataBlobs[sectionName] = sectionName;
  31. rowIDs[ii] = [];
  32. for (let jj = 0; jj < NUM_ROWS_PER_SECTION; jj++) {
  33. const rowName = `S${ii}, R${jj}`;
  34. rowIDs[ii].push(rowName);
  35. dataBlobs[rowName] = rowName;
  36. }
  37. }
  38. sectionIDs = [...sectionIDs];
  39. rowIDs = [...rowIDs];
  40. }
  41. class ListViewExample extends React.Component {
  42. constructor(props) {
  43. super(props);
  44. const getSectionData = (dataBlob, sectionID) => dataBlob[sectionID];
  45. const getRowData = (dataBlob, sectionID, rowID) => dataBlob[rowID];
  46. const dataSource = new ListView.DataSource({
  47. getRowData,
  48. getSectionHeaderData: getSectionData,
  49. rowHasChanged: (row1, row2) => row1 !== row2,
  50. sectionHeaderHasChanged: (s1, s2) => s1 !== s2,
  51. });
  52. this.state = {
  53. dataSource,
  54. isLoading: true,
  55. height: (document.documentElement.clientHeight * 3) / 4,
  56. };
  57. }
  58. componentDidMount() {
  59. const hei = document.documentElement.clientHeight - ReactDOM.findDOMNode(this.lv).parentNode.offsetTop;
  60. setTimeout(() => {
  61. genData();
  62. this.setState({
  63. dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlobs, sectionIDs, rowIDs),
  64. isLoading: false,
  65. height: hei,
  66. });
  67. }, 600);
  68. }
  69. onEndReached = (event) => {
  70. if (this.state.isLoading && !this.state.hasMore) {
  71. return;
  72. }
  73. console.log('reach end', event);
  74. this.setState({ isLoading: true });
  75. setTimeout(() => {
  76. genData(++pageIndex);
  77. this.setState({
  78. dataSource: this.state.dataSource.cloneWithRowsAndSections(dataBlobs, sectionIDs, rowIDs),
  79. isLoading: false,
  80. });
  81. }, 1000);
  82. }
  83. render() {
  84. const separator = (sectionID, rowID) => (
  85. <div
  86. key={`${sectionID}-${rowID}`}
  87. style={{
  88. backgroundColor: '#F5F5F9',
  89. height: 8,
  90. borderTop: '1px solid #ECECED',
  91. borderBottom: '1px solid #ECECED',
  92. }}
  93. />
  94. );
  95. let index = data.length - 1;
  96. const row = (rowData, sectionID, rowID) => {
  97. if (index < 0) {
  98. index = data.length - 1;
  99. }
  100. const obj = data[index--];
  101. return (
  102. <div key={rowID} style={{ padding: '0 15px' }}>
  103. <div
  104. style={{
  105. lineHeight: '50px',
  106. color: '#888',
  107. fontSize: 18,
  108. borderBottom: '1px solid #F6F6F6',
  109. }}
  110. >{obj.title}</div>
  111. <div style={{ display: 'flex', padding: '15px 0' }}>
  112. <img style={{ height: '64px', marginRight: '15px' }} src={obj.img} alt="" />
  113. <div style={{ lineHeight: 1 }}>
  114. <div style={{ marginBottom: '8px', fontWeight: 'bold' }}>{obj.des}</div>
  115. <div><span style={{ fontSize: '30px', color: '#FF6E27' }}>35</span>¥ {rowID}</div>
  116. </div>
  117. </div>
  118. </div>
  119. );
  120. };
  121. return (
  122. <ListView
  123. ref={el => this.lv = el}
  124. dataSource={this.state.dataSource}
  125. renderHeader={() => <span>header</span>}
  126. renderFooter={() => (<div style={{ padding: 30, textAlign: 'center' }}>
  127. {this.state.isLoading ? 'Loading...' : 'Loaded'}
  128. </div>)}
  129. renderSectionHeader={sectionData => (
  130. <div>{`Task ${sectionData.split(' ')[1]}`}</div>
  131. )}
  132. renderRow={row}
  133. renderSeparator={separator}
  134. style={{
  135. height: this.state.height,
  136. overflow: 'auto',
  137. }}
  138. pageSize={4}
  139. onScroll={() => { console.log('scroll'); }}
  140. scrollRenderAheadDistance={500}
  141. onEndReached={this.onEndReached}
  142. onEndReachedThreshold={10}
  143. />
  144. );
  145. }
  146. }
  147. class TabBarExample extends React.Component {
  148. constructor(props) {
  149. super(props);
  150. this.state = {
  151. selectedTab: 'blueTab',
  152. hidden: false,
  153. };
  154. }
  155. renderContent(pageText) {
  156. return (
  157. <div style={{ backgroundColor: 'white', height: '100%', textAlign: 'center' }}>
  158. <div style={{ paddingTop: 60 }}>Clicked “{pageText}” tab show “{pageText}” information</div>
  159. <a style={{ display: 'block', marginTop: 40, marginBottom: 20, color: '#108ee9' }}
  160. onClick={(e) => {
  161. e.preventDefault();
  162. this.setState({
  163. hidden: !this.state.hidden,
  164. });
  165. }}
  166. >
  167. Click to show/hide tab-bar
  168. </a>
  169. </div>
  170. );
  171. }
  172. render() {
  173. return (
  174. <div style={{ position: 'fixed', height: '100%', width: '100%', top: 0 }}>
  175. <TabBar
  176. unselectedTintColor="#949494"
  177. tintColor="#33A3F4"
  178. barTintColor="white"
  179. tabBarPosition="bottom"
  180. hidden={this.state.hidden}
  181. prerenderingSiblingsNumber={0}
  182. >
  183. <TabBar.Item
  184. title="Life"
  185. key="Life"
  186. icon={<div style={{
  187. width: '22px',
  188. height: '22px',
  189. background: 'url(https://zos.alipayobjects.com/rmsportal/sifuoDUQdAFKAVcFGROC.svg) center center / 21px 21px no-repeat' }}
  190. />
  191. }
  192. selectedIcon={<div style={{
  193. width: '22px',
  194. height: '22px',
  195. background: 'url(https://zos.alipayobjects.com/rmsportal/iSrlOTqrKddqbOmlvUfq.svg) center center / 21px 21px no-repeat' }}
  196. />
  197. }
  198. selected={this.state.selectedTab === 'blueTab'}
  199. badge={1}
  200. onPress={() => {
  201. this.setState({
  202. selectedTab: 'blueTab',
  203. });
  204. }}
  205. data-seed="logId"
  206. >
  207. <ListViewExample />
  208. </TabBar.Item>
  209. <TabBar.Item
  210. icon={
  211. <div style={{
  212. width: '22px',
  213. height: '22px',
  214. background: 'url(https://gw.alipayobjects.com/zos/rmsportal/BTSsmHkPsQSPTktcXyTV.svg) center center / 21px 21px no-repeat' }}
  215. />
  216. }
  217. selectedIcon={
  218. <div style={{
  219. width: '22px',
  220. height: '22px',
  221. background: 'url(https://gw.alipayobjects.com/zos/rmsportal/ekLecvKBnRazVLXbWOnE.svg) center center / 21px 21px no-repeat' }}
  222. />
  223. }
  224. title="Koubei"
  225. key="Koubei"
  226. badge={'new'}
  227. selected={this.state.selectedTab === 'redTab'}
  228. onPress={() => {
  229. this.setState({
  230. selectedTab: 'redTab',
  231. });
  232. }}
  233. data-seed="logId1"
  234. >
  235. {this.renderContent('Koubei')}
  236. </TabBar.Item>
  237. <TabBar.Item
  238. icon={
  239. <div style={{
  240. width: '22px',
  241. height: '22px',
  242. background: 'url(https://zos.alipayobjects.com/rmsportal/psUFoAMjkCcjqtUCNPxB.svg) center center / 21px 21px no-repeat' }}
  243. />
  244. }
  245. selectedIcon={
  246. <div style={{
  247. width: '22px',
  248. height: '22px',
  249. background: 'url(https://zos.alipayobjects.com/rmsportal/IIRLrXXrFAhXVdhMWgUI.svg) center center / 21px 21px no-repeat' }}
  250. />
  251. }
  252. title="Friend"
  253. key="Friend"
  254. dot
  255. selected={this.state.selectedTab === 'greenTab'}
  256. onPress={() => {
  257. this.setState({
  258. selectedTab: 'greenTab',
  259. });
  260. }}
  261. >
  262. {this.renderContent('Friend')}
  263. </TabBar.Item>
  264. <TabBar.Item
  265. icon={{ uri: 'https://zos.alipayobjects.com/rmsportal/asJMfBrNqpMMlVpeInPQ.svg' }}
  266. selectedIcon={{ uri: 'https://zos.alipayobjects.com/rmsportal/gjpzzcrPMkhfEqgbYvmN.svg' }}
  267. title="My"
  268. key="my"
  269. selected={this.state.selectedTab === 'yellowTab'}
  270. onPress={() => {
  271. this.setState({
  272. selectedTab: 'yellowTab',
  273. });
  274. }}
  275. >
  276. {this.renderContent('My')}
  277. </TabBar.Item>
  278. </TabBar>
  279. </div>
  280. );
  281. }
  282. }
  283. ReactDOM.render(<TabBarExample />, mountNode);
  1. .am-tab-bar::-webkit-scrollbar {
  2. display: none;
  3. }
  4. #tab-bar.demo {
  5. display: flex;
  6. flex-direction: column;
  7. }
  8. #tab-bar .demoName {
  9. height: 40px;
  10. }
  11. #tab-bar .demo-preview-item .am-tab-bar {
  12. background-color: white;
  13. }

Tabbar 在顶部

控制 Tabbar 显示在顶部

  1. import { TabBar } from 'antd-mobile';
  2. class TabBarExample extends React.Component {
  3. constructor(props) {
  4. super(props);
  5. this.state = {
  6. selectedTab: 'redTab',
  7. hidden: false,
  8. fullScreen: false,
  9. };
  10. }
  11. renderContent(pageText) {
  12. return (
  13. <div style={{ backgroundColor: 'white', height: '100%', textAlign: 'center' }}>
  14. <div style={{ paddingTop: 60 }}>Clicked “{pageText}” tab show “{pageText}” information</div>
  15. <a style={{ display: 'block', marginTop: 40, marginBottom: 20, color: '#108ee9' }}
  16. onClick={(e) => {
  17. e.preventDefault();
  18. this.setState({
  19. hidden: !this.state.hidden,
  20. });
  21. }}
  22. >
  23. Click to show/hide tab-bar
  24. </a>
  25. <a style={{ display: 'block', marginBottom: 600, color: '#108ee9' }}
  26. onClick={(e) => {
  27. e.preventDefault();
  28. this.setState({
  29. fullScreen: !this.state.fullScreen,
  30. });
  31. }}
  32. >
  33. Click to switch fullscreen
  34. </a>
  35. </div>
  36. );
  37. }
  38. render() {
  39. return (
  40. <div style={this.state.fullScreen ? { position: 'fixed', height: '100%', width: '100%', top: 0 } : { height: 400 }}>
  41. <TabBar
  42. unselectedTintColor="#949494"
  43. tintColor="#33A3F4"
  44. barTintColor="white"
  45. hidden={this.state.hidden}
  46. tabBarPosition="top"
  47. >
  48. <TabBar.Item
  49. title="Life"
  50. key="Life"
  51. icon={<div style={{
  52. width: '22px',
  53. height: '22px',
  54. background: 'url(https://zos.alipayobjects.com/rmsportal/sifuoDUQdAFKAVcFGROC.svg) center center / 21px 21px no-repeat' }}
  55. />
  56. }
  57. selectedIcon={<div style={{
  58. width: '22px',
  59. height: '22px',
  60. background: 'url(https://zos.alipayobjects.com/rmsportal/iSrlOTqrKddqbOmlvUfq.svg) center center / 21px 21px no-repeat' }}
  61. />
  62. }
  63. selected={this.state.selectedTab === 'blueTab'}
  64. badge={1}
  65. onPress={() => {
  66. this.setState({
  67. selectedTab: 'blueTab',
  68. });
  69. }}
  70. data-seed="logId"
  71. >
  72. {this.renderContent('Life')}
  73. </TabBar.Item>
  74. <TabBar.Item
  75. icon={
  76. <div style={{
  77. width: '22px',
  78. height: '22px',
  79. background: 'url(https://gw.alipayobjects.com/zos/rmsportal/BTSsmHkPsQSPTktcXyTV.svg) center center / 21px 21px no-repeat' }}
  80. />
  81. }
  82. selectedIcon={
  83. <div style={{
  84. width: '22px',
  85. height: '22px',
  86. background: 'url(https://gw.alipayobjects.com/zos/rmsportal/ekLecvKBnRazVLXbWOnE.svg) center center / 21px 21px no-repeat' }}
  87. />
  88. }
  89. title="Koubei"
  90. key="Koubei"
  91. badge={'new'}
  92. selected={this.state.selectedTab === 'redTab'}
  93. onPress={() => {
  94. this.setState({
  95. selectedTab: 'redTab',
  96. });
  97. }}
  98. data-seed="logId1"
  99. >
  100. {this.renderContent('Koubei')}
  101. </TabBar.Item>
  102. <TabBar.Item
  103. icon={
  104. <div style={{
  105. width: '22px',
  106. height: '22px',
  107. background: 'url(https://zos.alipayobjects.com/rmsportal/psUFoAMjkCcjqtUCNPxB.svg) center center / 21px 21px no-repeat' }}
  108. />
  109. }
  110. selectedIcon={
  111. <div style={{
  112. width: '22px',
  113. height: '22px',
  114. background: 'url(https://zos.alipayobjects.com/rmsportal/IIRLrXXrFAhXVdhMWgUI.svg) center center / 21px 21px no-repeat' }}
  115. />
  116. }
  117. title="Friend"
  118. key="Friend"
  119. dot
  120. selected={this.state.selectedTab === 'greenTab'}
  121. onPress={() => {
  122. this.setState({
  123. selectedTab: 'greenTab',
  124. });
  125. }}
  126. >
  127. {this.renderContent('Friend')}
  128. </TabBar.Item>
  129. <TabBar.Item
  130. icon={{ uri: 'https://zos.alipayobjects.com/rmsportal/asJMfBrNqpMMlVpeInPQ.svg' }}
  131. selectedIcon={{ uri: 'https://zos.alipayobjects.com/rmsportal/gjpzzcrPMkhfEqgbYvmN.svg' }}
  132. title="My"
  133. key="my"
  134. selected={this.state.selectedTab === 'yellowTab'}
  135. onPress={() => {
  136. this.setState({
  137. selectedTab: 'yellowTab',
  138. });
  139. }}
  140. >
  141. {this.renderContent('My')}
  142. </TabBar.Item>
  143. </TabBar>
  144. </div>
  145. );
  146. }
  147. }
  148. ReactDOM.render(<TabBarExample />, mountNode);
  1. #tab-bar.demo {
  2. display: flex;
  3. flex-direction: column;
  4. }
  5. #tab-bar .demoName {
  6. height: 40px;
  7. }
  8. #tab-bar .demo-preview-item .am-tab-bar {
  9. background-color: white;
  10. }

TabBar标签栏 - 图1

API

TabBar

属性说明类型默认值
barTintColortabbar 背景色Stringwhite
tintColor选中的字体颜色String#108ee9
unselectedTintColor未选中的字体颜色String'#888'
hidden是否隐藏Booleanfalse
prefixCls样式前缀String'am-tab-bar'
noRenderContent不渲染内容部分Booleanfalse
prerenderingSiblingsNumber预加载相邻的tab内容, Infinity: 加载所有的tab内容, 0: 仅加载当前tab内容, 当页面较复杂时,建议设为0,提升页面加载性能number1
tabBarPositiontabbar 位置'top'|'bottom''bottom'

TabBar.Item

属性说明类型默认值
badge徽标数Number \ String
dot是否在右上角显示小红点(在设置badge的情况下失效)Booleanfalse
onPressbar 点击触发,需要自己改变组件 state & selecte={true}Function(){}
selected是否选中Booleanfalse
icon默认展示图片见 demo
selectedIcon选中后的展示图片见 demo
title标题文字String
key唯一标识String