<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> 
 |