u-tabbar.vue 3.91 KB
   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
<template>
<view class="u-tabbar">
<view
class="u-tabbar__content"
ref="u-tabbar__content"
@touchmove.stop.prevent="noop"
:class="[border && 'u-border-top', fixed && 'u-tabbar--fixed']"
:style="[tabbarStyle]"
>
<view class="u-tabbar__content__item-wrapper">
<slot />
</view>
<u-safe-bottom v-if="safeAreaInsetBottom"></u-safe-bottom>
</view>
<view
class="u-tabbar__placeholder"
v-if="placeholder"
:style="{
height: placeholderHeight + 'px',
}"
></view>
</view>
</template>

<script>
import props from './props.js';
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin('dom')
// #endif
/**
* Tabbar 底部导航栏
* @description 此组件提供了自定义tabbar的能力。
* @tutorial https://www.uviewui.com/components/tabbar.html
* @property {String | Number} value 当前匹配项的name
* @property {Boolean} safeAreaInsetBottom 是否为iPhoneX留出底部安全距离(默认 true )
* @property {Boolean} border 是否显示上方边框(默认 true )
* @property {String | Number} zIndex 元素层级z-index(默认 1 )
* @property {String} activeColor 选中标签的颜色(默认 '#1989fa' )
* @property {String} inactiveColor 未选中标签的颜色(默认 '#7d7e80' )
* @property {Boolean} fixed 是否固定在底部(默认 true )
* @property {Boolean} placeholder fixed定位固定在底部时,是否生成一个等高元素防止塌陷(默认 true )
* @property {Object} customStyle 定义需要用到的外部样式
*
* @example <u-tabbar :value="value2" :placeholder="false" @change="name => value2 = name" :fixed="false" :safeAreaInsetBottom="false"><u-tabbar-item text="首页" icon="home" dot ></u-tabbar-item></u-tabbar>
*/
export default {
name: 'u-tabbar',
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
data() {
return {
placeholderHeight: 0
}
},
computed: {
tabbarStyle() {
const style = {
zIndex: this.zIndex
}
// 合并来自父组件的customStyle样式
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
},
// 监听多个参数的变化,通过在computed执行对应的操作
updateChild() {
return [this.value, this.activeColor, this.inactiveColor]
},
updatePlaceholder() {
return [this.fixed, this.placeholder]
}
},
watch: {
updateChild() {
// 如果updateChildren中的元素发生了变化,则执行子元素初始化操作
this.updateChildren()
},
updatePlaceholder() {
// 如果fixed,placeholder等参数发生变化,重新计算占位元素的高度
this.setPlaceholderHeight()
}
},
created() {
this.children = []
},
mounted() {
this.setPlaceholderHeight()
},
methods: {
updateChildren() {
// 如果存在子元素,则执行子元素的updateFromParent进行更新数据
this.children.length && this.children.map(child => child.updateFromParent())
},
// 设置用于防止塌陷元素的高度
async setPlaceholderHeight() {
if (!this.fixed || !this.placeholder) return
// 延时一定时间
await uni.$u.sleep(20)
// #ifndef APP-NVUE
this.$uGetRect('.u-tabbar__content').then(({height = 50}) => {
// 修复IOS safearea bottom 未填充高度
this.placeholderHeight = height
})
// #endif

// #ifdef APP-NVUE
dom.getComponentRect(this.$refs['u-tabbar__content'], (res) => {
const {
size
} = res
this.placeholderHeight = size.height
})
// #endif
}
}
}
</script>

<style lang="scss" scoped>
@import "../../libs/css/components.scss";

.u-tabbar {
@include flex(column);
flex: 1;
justify-content: center;
&__content {
@include flex(column);
background-color: #fff;
&__item-wrapper {
height: 50px;
@include flex(row);
}
}

&--fixed {
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
}
</style>