文章目录
- 一、组件介绍
 - 1、Tabs
 - 参数
 - 属性
 - 事件
 - TabsController
 
- 2、子组件
 - 属性
 - 说明
 
- 二、基础示例
 - 1、基础顶部导航
 - 2、效果
 - 3、可以滚动导航栏
 - 2、效果
 
- 三、扩展示例
 - 自定义导航栏
 - 1、代码
 - 2、效果
 
一、组件介绍
Tabs组件的页面组成包含两个部分,分别是TabContent和TabBar。TabContent是内容页,TabBar是导航页签栏,页面结构如下图所示,根据不同的导航类型,布局会有区别,可以分为底部导航、顶部导航、侧边导航,其导航栏分别位于底部、顶部和侧边。

1、Tabs
通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。
仅可包含子组件TabContent。
Tabs(value?: {barPosition?: BarPosition, index?: number, controller?: TabsController})
 
参数
| 参数名 | 参数类型 | 必填 | 参数描述 | 
|---|---|---|---|
| barPosition | BarPosition | 否 | 设置Tabs的页签位置。 默认值:BarPosition.Start  | 
| index | number | 否 | 设置当前显示页签的索引。 默认值:0 说明: 设置为小于0的值时按默认值显示。 可选值为[0, TabContent子节点数量-1]。 设置不同值时,默认生效切换动效,可以设置animationDuration为0关闭动画。  | 
| controller | TabsController | 否 | 设置Tabs控制器。 | 
属性
| 名称 | 参数类型 | 描述 | 
|---|---|---|
| vertical | boolean | 设置为false是为横向Tabs,设置为true时为纵向Tabs。 默认值:false  | 
| scrollable | boolean | 设置为true时可以通过滑动页面进行页面切换,为false时不可滑动切换页面。 默认值:true  | 
| barMode | BarMode | TabBar布局模式,具体描述见BarMode枚举说明。 默认值:BarMode.Fixed  | 
| barWidth | number | TabBar的宽度值。 | 
| barHeight | number | TabBar的高度值。 | 
| animationDuration | number | 点击TabBar页签切换TabContent的动画时长。不设置时,点击TabBar页签切换TabContent无动画。 默认值:300 说明: 该参数不支持百分比设置;设置为小于0时,按默认值300ms显示。  | 
事件
onChange(event: (index: number) => void)
 
Tab页签切换后触发的事件。
- index:当前显示的index索引,索引从0开始计算。
 
触发该事件的条件:
- 1、TabContent支持滑动时,组件触发滑动时触发。
 - 2、通过控制器API接口调用。
 - 3、通过状态变量构造的属性值进行修改。
 - 4、通过页签处点击触发。
 
TabsController
Tabs组件的控制器,用于控制Tabs组件进行页签切换。不支持一个TabsController控制多个Tabs组件。
controller: TabsController = new TabsController()
changeIndex(value: number): void
 
参数:
| 参数名 | 参数类型 | 必填 | 参数描述 | 
|---|---|---|---|
| value | number | 是 | 页签在Tabs里的索引值,索引值从0开始。 说明: 设置小于0或大于最大数量的值时,该事件失效。  | 
2、子组件
TabContent()
 
属性
| 名称 | 参数类型 | 描述 | 
|---|---|---|
| tabBar | string | Resource | 
说明
- TabContent组件不支持设置通用宽度属性,其宽度默认撑满Tabs父组件。
 - TabContent组件不支持设置通用高度属性,其高度由Tabs父组件高度与TabBar组件高度决定。
 - vertical属性为false值,交换上述2个限制。
 - TabContent组件不支持内容过长时页面的滑动,如需页面滑动,可嵌套List使用。
 
二、基础示例
1、基础顶部导航
@Entry
@Component
struct TabsPage2 {
  build() {
    Column() {
      Tabs() {
        TabContent() {
          Text('首页的内容').fontSize(30)
        }
        .tabBar('首页')
        TabContent() {
          Text('推荐的内容').fontSize(30)
        }
        .tabBar('推荐')
        TabContent() {
          Text('发现的内容').fontSize(30)
        }
        .tabBar('发现')
        TabContent() {
          Text('我的内容').fontSize(30)
        }
        .tabBar("我的")
      }
    }
    .width('100%')
    .height('100%')
  }
}
 
2、效果

3、可以滚动导航栏
滚动导航栏可以用于顶部导航栏或者侧边导航栏的设置,内容分类较多,屏幕宽度无法容纳所有分类页签的情况下,需要使用可滚动的导航栏,支持用户点击和滑动来加载隐藏的页签内容。
滚动导航栏需要设置Tabs组件的barMode属性,默认情况下其值为Fixed,表示为固定导航栏,设置为Scrollable即可设置为可滚动导航栏。
@Entry
@Component
struct TabsPage2 {
  @State tabsList: Array<string> = ['关注', '视频', '游戏', '数码', '科技', '体育', '影视', '人文', '艺术', '自然', '军事'];
  build() {
    Column() {
      Tabs() {
        ForEach(this.tabsList, (item) => {
          TabContent() {
            Text(item).fontSize(30)
          }
          .tabBar(item)
        })
      }.barMode(BarMode.Scrollable)
    }
    .width('100%')
    .height('100%')
  }
}
 
2、效果

三、扩展示例
自定义导航栏
对于底部导航栏,一般作为应用主页面功能区分,为了更好的用户体验,会组合文字以及对应语义图标表示页签内容,这种情况下,需要自定义导航页签的样式。
系统默认情况下采用了下划线标志当前活跃的页签,而自定义导航栏需要自行实现相应的样式,用于区分当前活跃页签和未活跃页签。设置自定义导航栏需要使用tabBar的参数,以其支持的CustomBuilder的方式传入自定义的函数组件样式。例如这里声明TabBuilder的自定义函数组件,传入参数包括页签文字title,对应位置index,以及选中状态和未选中状态的图片资源。通过当前活跃的currentIndex和页签对应的targetIndex匹配与否,决定UI显示的样式。
-  
在TabContent对应tabBar属性中传入自定义函数组件,并传递相应的参数。
 -  
在不使用自定义导航栏时,系统默认的Tabs会实现切换逻辑。在使用了自定义导航栏后,切换页签的逻辑需要手动实现。即用户点击对应页签时,屏幕需要显示相应的内容页 。
 -  
切换指定页签需要使用TabsController,TabsController是Tabs组件的控制器,用于控制Tabs组件进行页签切换。通过TabsController的changeIndex方法来实现跳转至指定索引值对应的TabContent内容。
 -  
使用自定义导航栏时,在tabBar属性中传入对应的@Builder,并传入相应的参数。
 
1、代码
tabsPage.ets
import {Cate} from "./tabs/cate"
import {Cart} from "./tabs/cart"
import {Msg} from "./tabs/msg"
import {User} from "./tabs/user"
@Entry
@Component
struct TabsPage {
  @State currentIndex: number = 0
  private tabsController: TabsController = new TabsController()
  @Builder TabBuilder(title:string,targetIndex:number,normalImg:Resource,selectedImg:Resource){
    Column(){
      Image(this.currentIndex==targetIndex?selectedImg:normalImg)
        .width(28)
        .height(28)
      Text(title)
        .fontSize(14)
        .margin({top:4})
        .fontColor(this.currentIndex==targetIndex?'#45C461':'#999999')
    }
    .backgroundColor("#ffffff")
    .width('100%')
    .height(60)
    .justifyContent(FlexAlign.Center)
    .onClick(()=>{
      this.currentIndex=targetIndex
      this.tabsController.changeIndex(this.currentIndex)
    })
  }
  build() {
    Column() {
      Tabs({barPosition:BarPosition.End,controller:this.tabsController,index:0}){
        TabContent(){
          Cate()
        }.tabBar(this.TabBuilder('分类',0,$r("app.media.tabs_1_off"),$r("app.media.tabs_1_on")))
        TabContent(){
          Cart()
        }.tabBar(this.TabBuilder('购物车',1,$r("app.media.tabs_2_off"),$r("app.media.tabs_2_on")))
        TabContent(){
          Msg()
        }.tabBar(this.TabBuilder('消息',2,$r("app.media.tabs_3_off"),$r("app.media.tabs_3_on")))
        TabContent(){
          User()
        }.tabBar(this.TabBuilder('我的',3,$r("app.media.tabs_4_off"),$r("app.media.tabs_4_on")))
      }
      .scrollable(false)//去掉左右滑动的效果
      .animationDuration(0)//去掉左右滑动的动画
    }
    .backgroundColor("#eeeeee")
    .width('100%')
    .height('100%')
  }
}
 
tabs/cart.ets
@Component
export struct Cart {
  build(){
    Text("购物车")
  }
}
 
其他页面内容都一样,自行编写。
2、效果


![【CTF Web】NSSCTF 3868 [LitCTF 2023]这是什么?SQL !注一下 !Writeup(SQL注入+报错注入+括号闭合+DIOS)](https://img-blog.csdnimg.cn/direct/71c8c6ac12a04c00be3b090839564565.png)


















