标签页(Tabs)

内容组之间进行导航切换。当前内容需要分成同层级结构的组,进行内容切换展示,用在表单或者标准列表界面的顶部。

重要
  • 目前一个页面中仅支持使用一次 Tabs 组件。

  • 在基础库 2.x 版本下,内嵌 scroll-view 产生 scroll-view 无法滚动的情况,建议 scroll-view 阻止 touch 事件冒泡:catchTouchStart、catchTouchMove。

  • Tabs 内部使用 transform 样式以进行轮播,会导致内嵌弹层显示问题,建议内部不嵌套包含弹层的组件或者使用 fallback 属性,以自己实现简单版的“轮播”,详见下方 fallback 的 demo。

属性

Tabs

属性

类型

必填

默认值

说明

adjustHeight

string

'current'

自动以指定滑块的高度为整个容器的高度。

activeClass

string

''

swiper-item 可见时的 class。

animation

boolean

false

是否有过渡动画。

className

string

-

类名

easingFunction

string

'default'

切换缓动动画类型

index

number

0

当前激活的索引。

nextMargin

string

'0px'

后边距,单位 px,1.9.0 版本暂时只支持水平方向。

plus

string | slot

-

右上角操作按钮,自定义节点

previousMargin

string

'0px'

前边距,单位 px,1.9.0 版本暂时只支持水平方向。

snapToEdge

boolean

false

当 swiper-item 个数大于等于 2,关闭 circular 并且开启 previous-margin 或 next-margin 时,可以指定这个边距是否应用到第一个、最后一个元素。

sticky

boolean

false

是否支持吸顶

swipeRatio

number

0.2

用户左右滑动手势触发切换的阈值,当滑动距离超过阈值时进行 swiper-item 切换。

swipeSpeed

number

0.05

用户左右滑动手势对应的滑动距离,数值越小则需要用户手势相同位移下 swiper-item 位移越小。

swipeable

boolean

false

是否支持手势切换。

title

slot-scope

-

自定义 tab 标题样式,仅在 type 为 basis 时可用。

touchAngle

number

45

用户左右滑动手势生效的滑动角度。角度根据 touchstart 事件和首次 touchmove 事件的坐标计算得出。数值越小越对用户的滑动方向准确度要求越高。

type

'basis' | 'capsule' | 'mixin'

'basis'

类型

  • basis:基础

  • capsule:胶囊

  • mixin:混合

TabItem

属性

类型

必填

默认值

说明

tab

{title: string; subTitle?: string; badge?: number; disabled?: boolean}[]

-

每一项 tab 内容

className

string

-

类名

事件

事件名

说明

类型

onChange

面板切换时候,触发回调

(index: number) => void

onAnimationEnd

内部 swiper 组件的 onAnimationEnd 事件(仅在基础库 1.50.0 以上版本生效)

(e: any) => void=> void

onTouchStart

内部 swiper 组件的 onTouchStart 事件(仅在基础库 2.x 版本生效)

(e: any) => void

onTransition

内部 swiper 组件的 onTransition 事件(仅在基础库 2.x 版本生效)

(e: any) => void

插槽

Tabs

名称

说明

plus

表单项额外内容

作用域插槽

Tabs

名称

说明

title

自定义 tab 标题样式。

样式类

Tabs

类名

说明

amd-tabs

整体样式。

amd-tabs-bar

上方标题区域样式。

amd-tabs-bar-active

上方标题区域激活时样式。

amd-tabs-bar-active:after

上方标题区域激活时 indicator 样式。

amd-tabs-bar

上方标题区域样式。

amd-tabs-bar-sticky

吸顶状态样式。

amd-tabs-bar-plus

右上角标签样式。

amd-tabs-bar-fade

两侧渐淡效果样式。

amd-tabs-bar-fade-left

左侧渐淡效果样式。

amd-tabs-bar-fade-right

右侧渐淡效果样式。

amd-tabs-bar-scroll-view

内部 ScrollView 组件样式。

amd-tabs-bar-wrap

每个标题的样式。

amd-tabs-bar-item

每个标题的样式。

amd-tabs-bar-basis

type 为 basis 时,每个标题的样式。

amd-tabs-bar-capsule

type 为 capsule 时,每个标题的样式。

amd-tabs-bar-capsule-title

type 为 capsule 时,每个标题内部文字的样式。

amd-tabs-bar-capsule-badge

type 为 capsule 时,每个标题内部 badge 的样式。

amd-tabs-bar-mixin

内type 为 mixin 时,每个标题的样式。

amd-tabs-bar-mixin-title

内type 为 mixin 时,每个标题的文字样式。

amd-tabs-bar-mixin-subtitle

内type 为 mixin 时,每个标题的副标题样式。

amd-tabs-bar-disabled

禁用态选项卡样式。

TabItem

类名

说明

amd-tabs-item

选项卡菜单的样式。

amd-tabs-item-pane

选项卡下面的内容面板样式。

代码示例

基本使用

index.axml 的代码示例如下:

<view>
  <tabs 
    index="{{index}}" 
    type="{{type}}" 
    animation="{{animation}}" 
    swipeable="{{swipeable}}" 
    sticky="{{sticky}}"
    onChange="handleChangeTab">
    <view a:if="{{plusSlot}}" slot="plus" >
      <icon 
        size="small"
        type="AddOutline" 
        className="plus-icon"
        onTap="handleClickIcon" />
    </view>
    <view 
      a:if="{{titleSlot}}"
      slot-scope="prop" 
      slot="title">
      {{prop.tab.title + ' slot'}}
    </view> 
    <block a:for="{{tabs}}">
      <tab-content 
        a:if="{{index === 1}}" 
        tab="{{item}}">
        <view>
          {{item.title}}
            <view 
              a:for="{{height}}">
              ........根据内容自适应高度........
            </view>
        </view>
      </tab-content>

      <tab-content 
        a:elif="{{index === 3}}"
        tab="{{item}}">
        <view style="height: 30vh">
          ........{{item.title}}........
          <text>父级设置了高度后的变化</text>
        </view>
      </tab-content>

      <tab-content tab="{{item}}" a:else badge="{{item.badge}}">
        <view style="height: 20vh">
          ........{{item.title}}........
        </view>
      </tab-content>

    </block>
  </tabs>
  <list radius className="actions">
    <list-item>
      选项数
      <radio-group 
        slot="extra"
        class="radio-group"
        name="tabsNumber" 
        onChange="handleChangeTabNum" >
        <label 
          class="radio" 
          a:for="{{tabsNumber}}">
          <radio 
            value="{{item.name}}" 
            checked="{{item.checked}}" />
          <text 
            class="radio-text">
            {{item.value}}
          </text>
        </label>
      </radio-group>
    </list-item>
    <list-item>
      type
      <radio-group 
        slot="extra"
        class="radio-group" 
        name="tabsType"
        onChange="handleChangeType" >
        <label 
          class="radio" 
          a:for="{{tabsType}}">
          <radio 
            value="{{item.name}}" 
            checked="{{item.checked}}" />
          <text 
            class="radio-text">
            {{item.value}}
          </text>
        </label>
      </radio-group>
    </list-item>
    <list-item>
      内容过渡动画<switch checked="{{animation}}" controlled onChange="handleChangeAnimation" slot="extra"/>
    </list-item>
    <list-item>
      支持手势切换<switch checked="{{swipeable}}" controlled onChange="handleChangeSwipeable" slot="extra"/>
    </list-item>
    <list-item brief="sticky效果">
      吸顶<switch checked="{{sticky}}" controlled onChange="handleChangeSticky" slot="extra"/>
    </list-item>
    <list-item brief="自定义tab展示,优先级高于配置">
      title插槽<switch checked="{{titleSlot}}" controlled onChange="handleChangeTitleSlot" slot="extra"/>
    </list-item>
    <list-item brief="右上角操作按钮">
      plus插槽<switch checked="{{plusSlot}}" controlled onChange="handleChangePlusSlot" slot="extra"/>
    </list-item>
  </list>
</view>

index.js 的代码示例如下:

Page({
  data: {
    index: 0,
    height: 30,
    type: 'basis',
    animation: true,
    swipeable: true,
    titleSlot: false,
    plusSlot: true,
    sticky: false,
    tabs: [
      {
        title: '选项一',
        subTitle: '描述文案',
      },
      {
        title: '选项二',
        subTitle: '描述文案描述',
      },
      {
        title: '选项三',
        subTitle: '描述',
      },
    ],
    tabsType: [
      { name: 'basis', value: '普通', checked: true },
      { name: 'capsule', value: '胶囊' },
      { name: 'mixin', value: '带描述' },
    ],
    tabsNumber: [
      { name: '1', value: '一条' },
      { name: '2', value: '两条' },
      { name: '3', value: '三条', checked: true },
      { name: '-1', value: '很多' },
    ],
  },
  handleChangeAnimation(checked) {
    this.setData({ animation: checked });
  },
  handleChangeSwipeable(checked) {
    this.setData({ swipeable: checked });
  },
  handleChangeSticky(checked) {
    this.setData({ sticky: checked });
  },
  handleChangeTitleSlot(checked) {
    this.setData({ titleSlot: checked });
  },
  handleChangePlusSlot(checked) {
    this.setData({ plusSlot: checked });
  },
  handleChangeType(e) {
    this.setData({
      type: e.detail.value,
    });
  },
  // tabs 的点击回调
  handleChangeTab(e) {
    this.setData({
      index: e,
    });
  },
  // 右上角的 plus 区域点击事件
  handleClickIcon() {
    my.alert({
      title: 'slot="plus"',
      content: '自定义 slot 的 icon 被点击',
    });
  },
  handleChangeTabNum(e) {
    if (e.detail.value === '1') {
      this.setData({
        tabs: [
          {
            title: '选项',
            subTitle: '描述文案',
            badge: 6,
          },
        ],
      });
    } else if (e.detail.value === '2') {
      this.setData({
        tabs: [
          {
            title: '选项',
            subTitle: '描述文案',
          },
          {
            title: '选项二',
            subTitle: '描述文案描述',
          },
        ],
      });
    } else if (e.detail.value === '3') {
      this.setData({
        tabs: [
          {
            title: '选项一',
            subTitle: '描述文案',
          },
          {
            title: '选项二',
            subTitle: '描述文案描述',
          },
          {
            title: '选项三',
            subTitle: '描述',
          },
        ],
      });
    } else {
      this.setData({
        tabs: [
          {
            title: '选项一',
            subTitle: '描述文案',
          },
          {
            title: '选项二',
            subTitle: '描述文案描述',
          },
          {
            title: '选项三',
            subTitle: '描述',
          },
          {
            title: '4 Tab',
            subTitle: '描述',
            showBadge: true,
            badge: 1,
          },
          {
            title: '5 Tab',
            subTitle: '描述',
            badge: 999,
          },
          {
            title: '3 Tab',
            subTitle: '描述',
          },
          {
            title: '4 Tab',
            subTitle: '描述',
          },
          {
            title: '151111 Tab',
            subTitle: '描述',
          },
          {
            title: '42345 Tab',
            subTitle: '描述',
          },
          {
            title: '1511116787 Tab',
            subTitle: '描述',
          },
          {
            title: '42452 Tab',
            subTitle: '描述',
          },
          {
            title: '15451111 Tab',
          },
          {
            title: '4234 Tab',
            subTitle: '描述',
          },
          {
            title: '11251111 Tab',
            subTitle: '描述',
          },
          {
            title: '44123 Tab',
          },
          {
            title: '1531111 Tab',
            subTitle: '描述',
          },
          {
            title: '41 Tab',
          },
          {
            title: '15111111 Tab',
          },
        ],
      });
    }
  },
});

index.acss 的代码示例如下:

.actions {
  margin-top: 24px;
}
.amd-tabs-item-pane view {
  background-color: #fff;
  padding: 24rpx;
}

.plus-icon {
  font-size: 48rpx;
}

index.json 的代码示例如下:

{
  "defaultTitle": "Tabs",
  "usingComponents": {
    "tabs": "antd-mini/es/Tabs/index",
    "tab-content": "antd-mini/es/Tabs/TabItem/index",
    "icon": "antd-mini/es/Icon/index",
    "list": "antd-mini/es/List/index",
    "list-item": "antd-mini/es/List/ListItem/index",
    "switch": "antd-mini/es/Switch/index",
    "demo-block": "../../components/DemoBlock/index"
  }
}

fallback

index.axml 的代码示例如下:

<tabs 
  index="{{curIdx}}" 
  type="{{type}}" 
  fallback="{{true}}" 
  sticky="{{sticky}}"
  onChange="changeTab">
  <block a:for="{{tabs}}">
    <tab-content 
      style="{{curIdx===index ? '' : 'display:none'}}"
      tab="{{item}}">
      <view>
        {{item.title}}
          <view 
            a:for="{{height}}">
            ........根据内容自适应高度........
          </view>
      </view>
    </tab-content>
  </block>
</tabs>

index.js 的代码示例如下:

const component2 = my.canIUse('component2');

Page({
  data: {
    curIdx: 2,
    height: 30,
    type: 'basis',
    animation: false,
    swipeable: false,
    titleSlot: false,
    plusSlot: true,
    sticky: false,
    tabs: [
      {
        title: '选项一',
        subTitle: '描述文案',
        corner: true,
      },
      {
        title: '选项二',
        subTitle: '描述文案描述',
      },
      {
        title: '选项三',
        subTitle: '描述',
      },
    ],
    tabsType: [
      { name: 'basis', value: '普通', checked: true },
      { name: 'capsule', value: '胶囊' },
      { name: 'mixin', value: '带描述' },
    ],
    tabsNumber: [
      { name: '1', value: '一条' },
      { name: '2', value: '两条' },
      { name: '3', value: '三条' },
      { name: '-1', value: '很多', checked: true },
    ],
    tabsAnimation: [
      { name: true, value: 'true' },
      { name: false, value: 'false', checked: true },
    ],
    tabsSwipeable: [
      { name: true, value: 'true' },
      { name: false, value: 'false', checked: true },
    ],
    tabsTitleSlotScope: [
      { name: true, value: 'true' },
      { name: false, value: 'false', checked: true },
    ],
    tabsSticky: [
      { name: true, value: 'true' },
      { name: false, value: 'false', checked: true },
    ],
    tabsPlusSlotScope: [
      { name: true, value: 'true', checked: true },
      { name: false, value: 'false' },
    ],
    canSwipe: true,
  },
  onLoad() {
    if (!component2) {
      this.setData({
        canSwipe: component2,
      });
    }
  },
  // tabs 的点击回调
  changeTab(e) {
    this.setData({
      curIdx: e,
    });
  },
  // 右上角的 plus 区域点击事件
  iconClick() {
    my.alert({
      title: 'slot="plus"',
      content: '自定义 slot 的 icon 被点击',
    });
  },
});

index.json 的代码示例如下:

{
    "defaultTitle": "Tabs",
    "usingComponents": {
      "tabs": "antd-mini/es/Tabs/index",
      "tab-content": "antd-mini/es/Tabs/TabItem/index",
      "icon": "antd-mini/es/Icon/index"
    }
  }