You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
3.9 KiB
141 lines
3.9 KiB
<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>
|
|
|