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.
		
		
		
		
		
			
		
			
				
					
					
						
							237 lines
						
					
					
						
							7.1 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							237 lines
						
					
					
						
							7.1 KiB
						
					
					
				
								<!-- 自定义底部导航项 -->
							 | 
						|
								<template>
							 | 
						|
								  <view class="u-tabbar-item" :style="[addStyle(customStyle)]">
							 | 
						|
								    <view v-if="isCenter" class="tabbar-center-item">
							 | 
						|
								      <image class="center-image" :src="centerImage" mode="aspectFill"></image>
							 | 
						|
								    </view>
							 | 
						|
								    <template v-else>
							 | 
						|
								      <view class="u-tabbar-item__icon">
							 | 
						|
								        <uni-badge
							 | 
						|
								          absolute="rightTop"
							 | 
						|
								          size="small"
							 | 
						|
								          :text="badge || (dot ? 1 : null)"
							 | 
						|
								          :customStyle="badgeStyle"
							 | 
						|
								          :isDot="dot"
							 | 
						|
								        >
							 | 
						|
								          <image
							 | 
						|
								            v-if="icon"
							 | 
						|
								            :name="icon"
							 | 
						|
								            :color="isActive ? parentData.activeColor : parentData.inactiveColor"
							 | 
						|
								            :size="20"
							 | 
						|
								          ></image>
							 | 
						|
								          <block v-else>
							 | 
						|
								            <slot v-if="isActive" name="active-icon" />
							 | 
						|
								            <slot v-else name="inactive-icon" />
							 | 
						|
								          </block>
							 | 
						|
								        </uni-badge>
							 | 
						|
								      </view>
							 | 
						|
								
							 | 
						|
								      <slot name="text">
							 | 
						|
								        <text
							 | 
						|
								          class="u-tabbar-item__text"
							 | 
						|
								          :style="{
							 | 
						|
								            color: isActive ? parentData.activeColor : parentData.inactiveColor,
							 | 
						|
								          }"
							 | 
						|
								        >
							 | 
						|
								          {{ text }}
							 | 
						|
								        </text>
							 | 
						|
								      </slot>
							 | 
						|
								    </template>
							 | 
						|
								  </view>
							 | 
						|
								</template>
							 | 
						|
								
							 | 
						|
								<script>
							 | 
						|
								  /**
							 | 
						|
								   * TabbarItem 底部导航栏子组件
							 | 
						|
								   * @description 此组件提供了自定义tabbar的能力。
							 | 
						|
								   * @property {String | Number}  name    item标签的名称,作为与u-tabbar的value参数匹配的标识符
							 | 
						|
								   * @property {String}      icon    uView内置图标或者绝对路径的图片
							 | 
						|
								   * @property {String | Number}  badge    右上角的角标提示信息
							 | 
						|
								   * @property {Boolean}      dot      是否显示圆点,将会覆盖badge参数(默认 false )
							 | 
						|
								   * @property {String}      text    描述文本
							 | 
						|
								   * @property {Object | String}  badgeStyle  控制徽标的位置,对象或者字符串形式,可以设置top和right属性(默认 'top: 6px;right:2px;' )
							 | 
						|
								   * @property {Object}      customStyle  定义需要用到的外部样式
							 | 
						|
								   *
							 | 
						|
								   */
							 | 
						|
								  import { $parent, addStyle } from '@/sheep/helper';
							 | 
						|
								
							 | 
						|
								  export default {
							 | 
						|
								    name: 'su-tabbar-item',
							 | 
						|
								    props: {
							 | 
						|
								      customStyle: {
							 | 
						|
								        type: [Object, String],
							 | 
						|
								        default: () => ({}),
							 | 
						|
								      },
							 | 
						|
								      customClass: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								      // 跳转的页面路径
							 | 
						|
								      url: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								      // 页面跳转的类型
							 | 
						|
								      linkType: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: 'navigateTo',
							 | 
						|
								      },
							 | 
						|
								      // item标签的名称,作为与u-tabbar的value参数匹配的标识符
							 | 
						|
								      name: {
							 | 
						|
								        type: [String, Number, null],
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								      // uView内置图标或者绝对路径的图片
							 | 
						|
								      icon: {
							 | 
						|
								        icon: String,
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								      // 右上角的角标提示信息
							 | 
						|
								      badge: {
							 | 
						|
								        type: [String, Number, null],
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								      // 是否显示圆点,将会覆盖badge参数
							 | 
						|
								      dot: {
							 | 
						|
								        type: Boolean,
							 | 
						|
								        default: false,
							 | 
						|
								      },
							 | 
						|
								      // 描述文本
							 | 
						|
								      text: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								      // 控制徽标的位置,对象或者字符串形式,可以设置top和right属性
							 | 
						|
								      badgeStyle: {
							 | 
						|
								        type: Object,
							 | 
						|
								        default: ()=>{},
							 | 
						|
								      },
							 | 
						|
								      isCenter: {
							 | 
						|
								        type: Boolean,
							 | 
						|
								        default: false,
							 | 
						|
								      },
							 | 
						|
								      centerImage: {
							 | 
						|
								        type: String,
							 | 
						|
								        default: '',
							 | 
						|
								      },
							 | 
						|
								    },
							 | 
						|
								    data() {
							 | 
						|
								      return {
							 | 
						|
								        isActive: false, // 是否处于激活状态
							 | 
						|
								        addStyle,
							 | 
						|
								        parentData: {
							 | 
						|
								          value: null,
							 | 
						|
								          activeColor: '', // 选中标签的颜色
							 | 
						|
								          inactiveColor: '', // 未选中标签的颜色
							 | 
						|
								        },
							 | 
						|
								        parent: {},
							 | 
						|
								      };
							 | 
						|
								    },
							 | 
						|
								    created() {
							 | 
						|
								      this.init();
							 | 
						|
								    },
							 | 
						|
								    methods: {
							 | 
						|
								      getParentData(parentName = '') {
							 | 
						|
								        // 避免在created中去定义parent变量
							 | 
						|
								        if (!this.parent) this.parent = {};
							 | 
						|
								        // 这里的本质原理是,通过获取父组件实例(也即类似u-radio的父组件u-radio-group的this)
							 | 
						|
								        // 将父组件this中对应的参数,赋值给本组件(u-radio的this)的parentData对象中对应的属性
							 | 
						|
								        // 之所以需要这么做,是因为所有端中,头条小程序不支持通过this.parent.xxx去监听父组件参数的变化
							 | 
						|
								        // 此处并不会自动更新子组件的数据,而是依赖父组件u-radio-group去监听data的变化,手动调用更新子组件的方法去重新获取
							 | 
						|
								        this.parent = $parent.call(this, parentName);
							 | 
						|
								        if (this.parent.children) {
							 | 
						|
								          // 如果父组件的children不存在本组件的实例,才将本实例添加到父组件的children中
							 | 
						|
								          this.parent.children.indexOf(this) === -1 && this.parent.children.push(this);
							 | 
						|
								        }
							 | 
						|
								        if (this.parent && this.parentData) {
							 | 
						|
								          // 历遍parentData中的属性,将parent中的同名属性赋值给parentData
							 | 
						|
								          Object.keys(this.parentData).map((key) => {
							 | 
						|
								            this.parentData[key] = this.parent[key];
							 | 
						|
								          });
							 | 
						|
								        }
							 | 
						|
								      },
							 | 
						|
								      init() {
							 | 
						|
								        // 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
							 | 
						|
								        this.updateParentData();
							 | 
						|
								        if (!this.parent) {
							 | 
						|
								          console.log('u-tabbar-item必须搭配u-tabbar组件使用');
							 | 
						|
								        }
							 | 
						|
								        // 本子组件在u-tabbar的children数组中的索引
							 | 
						|
								        const index = this.parent.children.indexOf(this);
							 | 
						|
								        // 判断本组件的name(如果没有定义name,就用index索引)是否等于父组件的value参数
							 | 
						|
								        this.isActive = (this.name.split('?')[0] || index) === this.parentData.value;
							 | 
						|
								      },
							 | 
						|
								      updateParentData() {
							 | 
						|
								        // 此方法在mixin中
							 | 
						|
								        this.getParentData('su-tabbar');
							 | 
						|
								      },
							 | 
						|
								      // 此方法将会被父组件u-tabbar调用
							 | 
						|
								      updateFromParent() {
							 | 
						|
								        // 重新初始化
							 | 
						|
								        this.init();
							 | 
						|
								      },
							 | 
						|
								      clickHandler() {
							 | 
						|
								        this.$nextTick(() => {
							 | 
						|
								          const index = this.parent.children.indexOf(this);
							 | 
						|
								          const name = this.name || index;
							 | 
						|
								          // 点击的item为非激活的item才发出change事件
							 | 
						|
								          if (name !== this.parent.value) {
							 | 
						|
								            this.parent.$emit('change', name);
							 | 
						|
								          }
							 | 
						|
								          this.$emit('click', name);
							 | 
						|
								        });
							 | 
						|
								      },
							 | 
						|
								    },
							 | 
						|
								  };
							 | 
						|
								</script>
							 | 
						|
								
							 | 
						|
								<style lang="scss" scoped>
							 | 
						|
								  .tabbar-center-item {
							 | 
						|
								    height: 40px;
							 | 
						|
								    width: 40px;
							 | 
						|
								    display: flex;
							 | 
						|
								    align-items: center;
							 | 
						|
								    justify-content: center;
							 | 
						|
								    border-radius: 50%;
							 | 
						|
								    background-color: rebeccapurple;
							 | 
						|
								    transform: scale(1.3) translateY(-6px);
							 | 
						|
								    position: absolute;
							 | 
						|
								    z-index: 2;
							 | 
						|
								
							 | 
						|
								    .center-image {
							 | 
						|
								      width: 25px;
							 | 
						|
								      height: 25px;
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  .u-tabbar-item {
							 | 
						|
								    display: flex;
							 | 
						|
								    flex-direction: column;
							 | 
						|
								    align-items: center;
							 | 
						|
								    justify-content: center;
							 | 
						|
								    flex: 1;
							 | 
						|
								    position: relative;
							 | 
						|
								    z-index: 1;
							 | 
						|
								
							 | 
						|
								    &__icon {
							 | 
						|
								      display: flex;
							 | 
						|
								      position: relative;
							 | 
						|
								      width: 150rpx;
							 | 
						|
								      justify-content: center;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    &__text {
							 | 
						|
								      margin-top: 2px;
							 | 
						|
								      font-size: 12px;
							 | 
						|
								      color: var(--textSize);
							 | 
						|
								    }
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /* #ifdef MP */
							 | 
						|
								  // 由于小程序都使用shadow DOM形式实现,需要给影子宿主设置flex: 1才能让其撑开
							 | 
						|
								  :host {
							 | 
						|
								    flex: 1;
							 | 
						|
								  }
							 | 
						|
								
							 | 
						|
								  /* #endif */
							 | 
						|
								</style>
							 |