feat: 新增 Tabbar 标签栏组件

This commit is contained in:
xuqingkai 2023-10-12 12:38:18 +08:00 committed by weisheng
parent bc241acfc1
commit aa0bf19486
13 changed files with 700 additions and 12 deletions

View File

@ -1,7 +1,7 @@
/*
* @Author: weisheng
* @Date: 2023-07-27 10:26:09
* @LastEditTime: 2023-09-28 11:22:30
* @LastEditTime: 2023-10-10 22:42:54
* @LastEditors: weisheng
* @Description:
* @FilePath: \wot-design-uni\docs\.vitepress\config.ts
@ -196,6 +196,9 @@ export default defineConfig({
}, {
link: "/component/segmented",
text: "Segmented 分段器"
}, {
link: "/component/tabbar",
text: "Tabbar 标签栏"
}]
}, {

View File

@ -4,25 +4,180 @@
底部导航栏,用于在不同页面之间进行切换。
## 基础用法
`v-model` 为绑定值,表示选中标签的索引值或者名称。
```html
<wd-tabbar v-model="tabbar1">
<wd-tabbar-item title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item title="我的" icon="user"></wd-tabbar-item>
</wd-tabbar>
```
```typescript
import { ref } from 'vue'
const tabbar1 = ref('home')
```
## 通过名称匹配
通过设置 `name` 属性,可以通过名称匹配选中标签。
```html
<wd-tabbar v-model="tabbar1">
<wd-tabbar-item name="home" title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="cart" title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="setting" title="设置" icon="setting"></wd-tabbar-item>
<wd-tabbar-item name="user" title="我的" icon="user"></wd-tabbar-item>
</wd-tabbar>
```
## 徽标提示
通过设置 `value` 属性,可以显示徽标提示,而设置 is-dot 属性后,会在图标右上角展示一个小红点。
```html
<wd-tabbar v-model="tabbar5">
<wd-tabbar-item name="1" is-dot :value="2" title="点状" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" :value="2" icon="cart" title="分类"></wd-tabbar-item>
<wd-tabbar-item name="3" :value="30" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" :value="200" title="最大值" icon="user"></wd-tabbar-item>
</wd-tabbar>
```
## 悬浮标签栏
通过设置 `shape` 属性为 `round`,可以将标签栏设置为悬浮样式。
```html
<wd-tabbar shape="round" v-model="tabbar2">
<wd-tabbar-item name="1" title="首页" is-dot :value="2" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" title="分类" :value="2" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="3" title="相册" :value="30" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="4" title="我的" :value="200" icon="user"></wd-tabbar-item>
</wd-tabbar>
```
## 自定义图标
通过使用 `<template #icon>` 可以自定义标签页的图标。
```html
<wd-tabbar v-model="tabbar4">
<wd-tabbar-item name="1" :value="2" title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" :value="2" icon="cart" title="分类">
<template #icon>
<wd-img round height="40rpx" width="40rpx" src="https://unpkg.com/wot-design-uni-assets/panda.jpg"></wd-img>
</template>
</wd-tabbar-item>
<wd-tabbar-item name="3" :value="3" title="我的" icon="user"></wd-tabbar-item>
</wd-tabbar>
```
## 自定义颜色
通过设置 `active-color``inactive-color` 属性,可以自定义激活和未激活标签的颜色。
```html
<wd-tabbar v-model="tabbar5" active-color="#ee0a24" inactive-color="#7d7e80">
<wd-tabbar-item name="1" is-dot :value="2" title="点状" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" :value="2" icon="cart" title="分类"></wd-tabbar-item>
<wd-tabbar-item name="3" :value="30" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" :value="200" title="最大值" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="5" :value="10" title="客服" icon="chat"></wd-tabbar-item>
</wd-tabbar>
```
## 监听切换事件
通过监听 `change` 事件,可以获取选中标签的值。
```html
<wd-tabbar v-model="tabbar6" @change="handleChange1" active-color="#ee0a24" inactive-color="#7d7e80">
<wd-tabbar-item name="1" title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="3" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" title="相册" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="5" title="客服" icon="chat"></wd-tabbar-item>
</wd-tabbar>
```
```typescript
function handleChange1({ value }: { value: string }) {
show(`选中标签:${value}`)
}
```
## 固定底部
通过设置 `fixed` 属性,可以将标签栏固定在底部;通过设置 `placeholder` 属性,可以在固定在底部时在标签位置生成一个等高的占位元素。
```html
<wd-tabbar fixed v-model="tabbar3" bordered safeAreaInsetBottom placeholder>
<wd-tabbar-item name="1" :value="2" is-dot title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="3" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" :value="200" title="相册" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="5" :value="10" title="客服" icon="chat"></wd-tabbar-item>
</wd-tabbar>
```
## Attributes
## Tabbar Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
|-----------------------|--------------------------------------------|-----------------------------|--------------------------------------|-------------------|------------|
| v-model/modelValue | 选中标签的索引值或者名称 | number / string | - | 0 | 0.1.27 |
| fixed | 是否固定在底部 | boolean | - | false | 0.1.27 |
| safeAreaInsetBottom | 是否设置底部安全距离iPhone X 类型的机型) | boolean | - | - | 0.1.27 |
| safeAreaInsetBottom | 是否设置底部安全距离iPhone X 类型的机型) | boolean | - | false | 0.1.27 |
| bordered | 是否显示顶部边框 | boolean | - | true | 0.1.27 |
| shape | 标签栏的形状 | TabbarShape | 'default' / 'round' | 'default' | 0.1.27 |
| activeColor | 激活标签的颜色 | string | - | '' | 0.1.27 |
| inactiveColor | 未激活标签的颜色 | string | - | '' | 0.1.27 |
| activeColor | 激活标签的颜色 | string | - | - | 0.1.27 |
| inactiveColor | 未激活标签的颜色 | string | - | - | 0.1.27 |
| placeholder | 固定在底部时,是否在标签位置生成一个等高的占位元素 | boolean | - | false | 0.1.27 |
| zIndex | tabbar组件的层级 | number | - | 500 | 0.1.27 |
## 外部样式类
## Tabbar Events
| 事件名称 | 说明 | 参数 | 最低版本 |
| -------- | -------------------------- | ----------- | -------- |
| change | tabbar标签切换时触发 | `{ value }` | 0.1.27 |
## Tabbar 外部样式类
| 类名 | 说明 | 最低版本 |
|-----|-----|---------|
| custom-class | 根节点样式类 | - |
| custom-style | 根节点样式 | - |
| custom-class | 根节点样式类 | 0.1.27 |
| custom-style | 根节点样式 | 0.1.27 |
## TabbarItem Attributes
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
|--------------|----------------|-------------------------|----------------|----------|------------|
| title | 标签页的标题 | string | - | - | 0.1.27 |
| name | 唯一标识符 | string / number | - | - | 0.1.27 |
| icon | 图标 | string | - | - | 0.1.27 |
| value | 徽标显示值 | number / string | - | - | 0.1.27 |
| isDot | 是否点状徽标 | boolean | - | false | 0.1.27 |
| max | 徽标最大值 | number | - | 99 | 0.1.27 |
## TabbarItem Slots
| name | 说明 | 参数 | 最低版本 |
| ------ | -------------------- | ----------------------- | -------- |
| icon | 自定义图标 | `active: boolean` | 0.1.27 |
## TabbarItem 外部样式类
| 类名 | 说明 | 最低版本 |
|-----|-----|---------|
| custom-class | 根节点样式类 | 0.1.27 |
| custom-style | 根节点样式 | 0.1.27 |

View File

@ -591,6 +591,16 @@
},
"navigationBarTitleText": "Segmented 分段器"
}
},
{
"path": "pages/tabbar/Index",
"name": "tabbar",
"style": {
"mp-alipay": {
"allowsBounceVertical": "NO"
},
"navigationBarTitleText": "Tabbar 标签栏"
}
}
],
// "tabBar": {

View File

@ -98,6 +98,10 @@ const list = ref([
{
id: 'segmented',
name: 'Segmented 分段器'
},
{
id: 'tabbar',
name: 'Tabbar 标签栏'
}
]
},

View File

@ -93,11 +93,11 @@
import { ref } from 'vue'
const swiperList = ref([
'https://cdn.jsdelivr.net/npm/wot-design-uni-assets/redpanda.jpg',
'https://cdn.jsdelivr.net/npm/wot-design-uni-assets/capybara.jpg',
'https://cdn.jsdelivr.net/npm/wot-design-uni-assets/panda.jpg',
'https://unpkg.com/wot-design-uni-assets/redpanda.jpg',
'https://unpkg.com/wot-design-uni-assets/capybara.jpg',
'https://unpkg.com/wot-design-uni-assets/panda.jpg',
'https://img.yzcdn.cn/vant/cat.jpeg',
'https://cdn.jsdelivr.net/npm/wot-design-uni-assets/meng.jpg'
'https://unpkg.com/wot-design-uni-assets/meng.jpg'
])
function handleClick(e) {
console.log(e)

103
src/pages/tabbar/Index.vue Normal file
View File

@ -0,0 +1,103 @@
<template>
<page-wraper>
<wd-toast></wd-toast>
<demo-block hor="0" title="基础用法" transparent>
<wd-tabbar bordered @change="handleChange">
<wd-tabbar-item title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item title="我的" icon="user"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
<demo-block hor="0" title="通过名称匹配" transparent>
<wd-tabbar bordered @change="handleChange" v-model="tabbar1">
<wd-tabbar-item name="home" title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="cart" title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="setting" title="设置" icon="setting"></wd-tabbar-item>
<wd-tabbar-item name="user" title="我的" icon="user"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
<demo-block hor="0" title="徽标提示" transparent>
<wd-tabbar v-model="tabbar5" @change="handleChange">
<wd-tabbar-item name="1" is-dot :value="2" title="点状" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" :value="2" icon="cart" title="分类"></wd-tabbar-item>
<wd-tabbar-item name="3" :value="30" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" :value="200" title="最大值" icon="user"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
<demo-block hor="0" title="悬浮标签栏" transparent>
<wd-tabbar shape="round" v-model="tabbar2" @change="handleChange">
<wd-tabbar-item name="1" title="首页" is-dot :value="2" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" title="分类" :value="2" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="3" title="相册" :value="30" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="4" title="我的" :value="200" icon="user"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
<demo-block hor="0" title="自定义图标" transparent>
<wd-tabbar v-model="tabbar4" @change="handleChange">
<wd-tabbar-item name="1" :value="2" title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" :value="2" icon="cart" title="分类">
<template #icon>
<wd-img round height="40rpx" width="40rpx" src="https://img.yzcdn.cn/vant/cat.jpeg"></wd-img>
</template>
</wd-tabbar-item>
<wd-tabbar-item name="3" :value="3" title="我的" icon="user"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
<demo-block hor="0" title="自定义颜色" transparent>
<wd-tabbar v-model="tabbar5" @change="handleChange" active-color="#ee0a24" inactive-color="#7d7e80">
<wd-tabbar-item name="1" is-dot :value="2" title="点状" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" :value="2" icon="cart" title="分类"></wd-tabbar-item>
<wd-tabbar-item name="3" :value="30" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" :value="200" title="最大值" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="5" :value="10" title="客服" icon="chat"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
<demo-block hor="0" title="监听切换事件" transparent>
<wd-tabbar v-model="tabbar6" @change="handleChange1" active-color="#ee0a24" inactive-color="#7d7e80">
<wd-tabbar-item name="1" title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="3" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" title="相册" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="5" title="客服" icon="chat"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
<demo-block hor="0" title="固定底部" transparent>
<wd-tabbar fixed v-model="tabbar3" @change="handleChange" bordered safeAreaInsetBottom placeholder>
<wd-tabbar-item name="1" :value="2" is-dot title="首页" icon="home"></wd-tabbar-item>
<wd-tabbar-item name="2" title="分类" icon="cart"></wd-tabbar-item>
<wd-tabbar-item name="3" title="我的" icon="user"></wd-tabbar-item>
<wd-tabbar-item name="4" :value="200" title="相册" icon="photo"></wd-tabbar-item>
<wd-tabbar-item name="5" :value="10" title="客服" icon="chat"></wd-tabbar-item>
</wd-tabbar>
</demo-block>
</page-wraper>
</template>
<script lang="ts" setup>
import { useToast } from '@/uni_modules/wot-design-uni'
import { ref } from 'vue'
const { show } = useToast()
const tabbar1 = ref('home')
const tabbar2 = ref('2')
const tabbar3 = ref('2')
const tabbar4 = ref('1')
const tabbar5 = ref('1')
const tabbar6 = ref('1')
function handleChange(event: any) {
console.log(event)
}
function handleChange1({ value }: { value: string }) {
show(`选中标签:${value}`)
}
</script>
<style lang="scss" scoped>
:deep(.page-wraper) {
background: #f6f6f6;
}
</style>

View File

@ -762,8 +762,18 @@ $-swiper-nav-btn-size: var(--wot-swiper-nav-btn-size, 48rpx) !default;
// segmented
$-segmented-padding: var(--wot-segmented-padding, 4px) !default; // 分段器padding
$-segmented-item-bg-color: var(--wot-segmented-item-bg-color, #eeeeee) !default;
$-segmented-item-color: var(--wot-segmented-item-color, rgba(0, 0, 0, 0.85)) !default; // 标题文字颜色
$-segmented-item-acitve-bg: var(--wot-segmented-item-acitve-bg, #FFFFFF) !default; // 标题文字颜色
$-segmented-item-disabled-color: var(--wot-segmented-item-disabled-color, rgba(0, 0, 0, 0.25)) !default; // 标题文字禁用颜色
// tabbar
$-tabbar-height: var(--wot-tabbar-height, 50px) !default;
$-tabbar-box-shadow: var(--wot-tabbar-box-shadow, 0 6px 30px 5px rgba(0, 0, 0, 0.05), 0 16px 24px 2px rgba(0, 0, 0, 0.04), 0 8px 10px -5px rgba(0, 0, 0, 0.08)) !default; // round类型tabbar阴影
// tabbar-item
$-tabbar-item-title-font-size: var(--wot-tabbar-item-title-font-size, 10px) !default; // tabbar选项文字大小
$-tabbar-item-title-line-height: var(--wot-tabbar-item-title-line-height, initial) !default; // tabbar选项标题文字行高
$-tabbar-inactive-color: var(--wot-tabbar-inactive-color, $-color-title) !default; // 标题文字和图标颜色
$-tabbar-active-color: var(--wot-tabbar-active-color, $-color-theme) !default; // 选中文字和图标颜色

View File

@ -0,0 +1,51 @@
@import '../common/abstracts/variable';
@import '../common/abstracts/mixin';
.wot-theme-dark {
@include b(tabbar-item) {
@include e(body) {
:deep(){
@include when(inactive) {
color: $-dark-color-gray;
}
}
}
}
}
@include b(tabbar-item) {
flex: 1;
text-align: center;
text-decoration: none;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
@include e(body) {
display: flex;
align-items: center;
flex-direction: column;
line-height: 1;
padding: 0;
position: relative;
:deep(){
@include when(active) {
color: $-tabbar-active-color;
}
@include when(inactive) {
color: $-tabbar-inactive-color;
}
}
}
@include e(body-title) {
font-size: $-tabbar-item-title-font-size;
line-height: $-tabbar-item-title-line-height;
}
}

View File

@ -0,0 +1,7 @@
/**
*
*/
export interface TabbarItem {
// 唯一标识
name: string
}

View File

@ -0,0 +1,143 @@
<template>
<view class="wd-tabbar-item" :style="customStyle" @click="handleClick">
<wd-badge :modelValue="value" :isDot="isDot" :max="max" type="danger">
<view class="wd-tabbar-item__body">
<slot name="icon" :active="active"></slot>
<template v-if="!$slots.icon && icon">
<wd-icon :name="icon" size="20px" :custom-style="textStyle" :custom-class="active ? 'is-active' : 'is-inactive'"></wd-icon>
</template>
<text v-if="title" :style="textStyle" :class="`wd-tabbar-item__body-title ${active ? 'is-active' : 'is-inactive'}`">
{{ title }}
</text>
</view>
</wd-badge>
</view>
</template>
<script lang="ts">
export default {
name: 'wd-tabbar-item',
options: {
addGlobalClass: true,
virtualHost: true,
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import { type CSSProperties, computed, inject, onMounted, ref, watch, getCurrentInstance, reactive } from 'vue'
import { isDef, objToStyle } from '../common/util'
interface Props {
//
customClass?: string
//
customStyle?: string
//
title?: string
//
name?: string | number
//
icon?: string
//
value?: number | string | null
//
isDot?: boolean
//
max?: number
}
const props = withDefaults(defineProps<Props>(), {
customClass: '',
customStyle: '',
isDot: false,
max: 99
})
const { proxy } = getCurrentInstance() as any
const parent = inject<any>('wdtabbar', { value: '' }) //
const active = ref<boolean>(false) //
const index = ref<number>(0) // tabbar
const textStyle = computed(() => {
const style: CSSProperties = {}
if (active.value && parent.activeColor) {
style['color'] = parent.activeColor
}
if (!active.value && parent.inactiveColor) {
style['color'] = parent.inactiveColor
}
return `${objToStyle(style)}`
})
watch(
() => parent.modelValue,
(newVal: string | number) => {
const name = isDef(props.name) ? props.name : index.value
if (isDef(newVal)) {
if (newVal === name) {
active.value = true
} else {
active.value = false
}
} else {
active.value = false
}
},
{ deep: true }
)
onMounted(() => {
init()
})
/**
* 初始化将组件信息注入父组件
*/
function init() {
if (parent.children && isDef(props.name)) {
const repeat = checkRepeat(parent.children, props.name, 'name')
if (repeat > -1) {
throw Error('[wot-design] warning(wd-tabbar-item): name attribute cannot be defined repeatedly')
}
}
parent.setChild && parent.setChild(proxy)
index.value = parent.children.indexOf(proxy)
updateActive()
}
/**
* 更新展开状态
*/
function updateActive() {
if (parent && isDef(parent.modelValue)) {
const name = isDef(props.name) ? props.name : index.value
if (parent.modelValue === name) {
active.value = true
} else {
active.value = false
}
}
}
/**
* 检查是否存在重复name属性
* @param {Array} currentList
* @param {String} checkValue 比较的重复值
* @param {String} key 键名
*/
function checkRepeat(currentList: any[], checkValue: string | number, key: string): number {
return currentList.findIndex((item) => item[key] === checkValue)
}
/**
* 点击tabbar选项
*/
function handleClick() {
active.value = true
const name = isDef(props.name) ? props.name : index.value
parent.setChange && parent.setChange({ name })
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

View File

@ -0,0 +1,43 @@
@import '../common/abstracts/variable';
@import '../common/abstracts/mixin';
.wot-theme-dark {
@include b(tabbar) {
background: $-dark-background;
}
}
@include b(tabbar) {
display: flex;
align-items: center;
flex-wrap: nowrap;
position: relative;
background: $-color-white;
height: $-tabbar-height;
@include m(round){
margin-left: 32rpx;
margin-right: 32rpx;
border-radius: 999px;
box-shadow: $-tabbar-box-shadow;
}
@include when(border){
@include m(default){
@include halfPixelBorder('top');
}
}
@include when(fixed) {
position: fixed;
left: 0;
bottom: 0;
right: 0;
z-index: 500;
@include when(safe) {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
}
}

View File

@ -0,0 +1,157 @@
<template>
<view :style="{ height: addUnit(height) }">
<view
:class="`wd-tabbar wd-tabbar--${shape} ${customClass} ${fixed ? 'is-fixed' : ''} ${safeAreaInsetBottom ? 'is-safe' : ''} ${
bordered ? 'is-border' : ''
}`"
:style="rootStyle"
>
<slot></slot>
</view>
</view>
</template>
<script lang="ts">
export default {
name: 'wd-tabbar',
options: {
addGlobalClass: true,
virtualHost: true,
styleIsolation: 'shared'
}
}
</script>
<script lang="ts" setup>
import { getCurrentInstance, onMounted, provide, reactive, ref, watch, nextTick, computed, type CSSProperties } from 'vue'
import { TabbarItem } from '../wd-tabbar-item/types'
import { addUnit, getRect, isDef, objToStyle } from '../common/util'
type TabbarShape = 'default' | 'round'
interface Props {
//
customClass?: string
//
customStyle?: string
//
modelValue?: number | string
//
fixed?: boolean
// iphone X
safeAreaInsetBottom?: boolean
//
bordered?: boolean
// default/round
shape?: TabbarShape
//
activeColor?: string
//
inactiveColor?: string
//
placeholder?: boolean
//
zIndex?: number
}
const props = withDefaults(defineProps<Props>(), {
customClass: '',
customStyle: '',
modelValue: 0,
fixed: false,
bordered: true,
safeAreaInsetBottom: false,
shape: 'default',
inactiveColor: '',
activeColor: '',
placeholder: false,
zIndex: 500
})
const height = ref<number>(50) //
const parentData = reactive({
activeColor: props.activeColor,
inactiveColor: props.inactiveColor,
modelValue: props.modelValue,
children: [] as any[],
setChild,
setChange
})
const rootStyle = computed(() => {
const style: CSSProperties = {}
if (isDef(props.zIndex)) {
style['z-index'] = props.zIndex
}
return `${objToStyle(style)};${props.customStyle}`
})
const { proxy } = getCurrentInstance() as any
provide('wdtabbar', parentData)
watch(
() => props.modelValue,
(newValue) => {
parentData.modelValue = newValue
}
)
watch(
[() => props.fixed, () => props.placeholder],
() => {
setPlaceholderHeight()
},
{ deep: true, immediate: false }
)
onMounted(() => {
if (props.fixed && props.placeholder) {
nextTick(() => {
setPlaceholderHeight()
})
}
})
const emit = defineEmits(['change', 'update:modelValue'])
/**
* 设置子项
* @param child
*/
function setChild(child: any) {
const hasChild = parentData.children.indexOf(child)
if (hasChild === -1) {
parentData.children.push(child)
} else {
parentData.children[hasChild] = child
}
if (!isDef(props.modelValue) && parentData.children.length === 1) {
const name = isDef(parentData.children[0].name) ? parentData.children[0].name : 0
setChange({ name })
}
}
/**
* 子项状态变更
* @param child 子项
*/
function setChange(child: TabbarItem) {
let active = child.name
emit('update:modelValue', active)
parentData.modelValue = active
emit('change', {
value: active
})
}
function setPlaceholderHeight() {
if (!props.fixed || !props.placeholder) {
return
}
getRect('.wd-tabbar', false, proxy).then((res: any) => {
height.value = res.height
})
}
</script>
<style lang="scss" scoped>
@import './index.scss';
</style>

View File

@ -81,6 +81,8 @@ declare module '@vue/runtime-core' {
WdSwiper: typeof import('./components/wd-swiper/wd-swiper.vue')['default']
WdSwiperNav: typeof import('./components/wd-swiper-nav/wd-swiper-nav.vue')['default']
WdSegmented: typeof import('./components/wd-segmented/wd-segmented.vue')['default']
WdTabbar: typeof import('./components/wd-tabbar/wd-tabbar.vue')['default']
WdTabbarItem: typeof import('./components/wd-tabbar-item/wd-tabbar-item.vue')['default']
}
}