Browse Source

fix(tabbar): add custom Icon slot #1807 (#1852)

Drjingfubo 3 years ago
parent
commit
c489132080

+ 19 - 0
src/packages/__VUE/tabbar/demo.vue

@@ -48,6 +48,17 @@
       ></nut-tabbar-item>
     </nut-tabbar>
 
+    <h2>{{ translate('customIcon') }}</h2>
+    <nut-tabbar @tab-switch="tabSwitch">
+      <nut-tabbar-item :tab-title="translate('title')">
+        <template #icon="props">
+          <img :src="props.active ? icon.active : icon.unactive" alt="" />
+        </template>
+      </nut-tabbar-item>
+      <nut-tabbar-item :tab-title="translate('title')" icon="category"></nut-tabbar-item>
+      <nut-tabbar-item :tab-title="translate('title')" icon="find"></nut-tabbar-item>
+    </nut-tabbar>
+
     <h2>{{ translate('customCheck') }}</h2>
     <nut-tabbar v-model:visible="active" size="18px">
       <nut-tabbar-item :tab-title="translate('title')" icon="home"></nut-tabbar-item>
@@ -102,6 +113,7 @@ const initTranslate = () =>
       basic: '基本用法',
       byName: '通过名称匹配',
       customImg: '自定义图片',
+      customIcon: '自定义图标',
       customCheck: '自定义选中',
       showBadge: '徽标提示',
       customColor: '自定义颜色',
@@ -113,6 +125,7 @@ const initTranslate = () =>
       basic: 'Basic Usage',
       byName: 'Match by name',
       customImg: 'Custom Img',
+      customIcon: 'Custom Icon',
       customCheck: 'Custom Check',
       showBadge: 'Show Badge',
       customColor: 'Custom Color',
@@ -130,8 +143,14 @@ export default createDemo({
     function tabSwitch(item: Record<string, unknown>, index: number) {
       console.log(item, index);
     }
+    const icon = {
+      active: 'https://img11.360buyimg.com/imagetools/jfs/t1/70423/4/20553/3652/62e74629E23ba550e/aeeed0e3b9f43ae6.png',
+      unactive:
+        'https://img13.360buyimg.com/imagetools/jfs/t1/23319/19/18329/3084/62e7c346E957c54ef/6c3e8a49e52b76f2.png'
+    };
     return {
       active,
+      icon,
       activeName,
       tabSwitch,
       translate

+ 42 - 0
src/packages/__VUE/tabbar/doc.en-US.md

@@ -98,6 +98,42 @@ If you need to use more icons based on the existing Icon, please refer to the Ic
 ```
 :::
 
+### Custom Icon
+Use icon slot to custom icon.
+
+:::demo
+```html
+<template>
+  <nut-tabbar @tab-switch="tabSwitch">
+    <nut-tabbar-item tab-title="首页">
+      <template #icon="props">
+          <img :src="props.active ? icon.active : icon.unactive" alt="" />
+        </template>
+    </nut-tabbar-item>
+    <nut-tabbar-item tab-title="分类" icon="category"></nut-tabbar-item>
+    <nut-tabbar-item tab-title="发现" icon="find"></nut-tabbar-item>
+  </nut-tabbar>
+</template>
+<script>
+  export default{
+    setup() {
+      function tabSwitch(item, index) {
+        console.log(item, index);
+      }
+      const icon = {
+        active: 'https://img11.360buyimg.com/imagetools/jfs/t1/70423/4/20553/3652/62e74629E23ba550e/aeeed0e3b9f43ae6.png',
+        unactive:'https://img13.360buyimg.com/imagetools/jfs/t1/23319/19/18329/3084/62e7c346E957c54ef/6c3e8a49e52b76f2.png',
+      };
+      return {
+        icon,
+        tabSwitch,
+      };
+    },
+  }
+</script>
+```
+:::
+
 ### Custom Check
 :::demo
 ```html
@@ -203,6 +239,12 @@ If you need to use more icons based on the existing Icon, please refer to the Ic
 | dot       | Whether to show red dot   | boolean | false    |
 
 
+### TabbarItem Slots
+
+| Name   | Description               | SlotProps           |
+|------------|--------------------|--------------------|
+| icon | Custom Icon	 | active: boolean |
+
 ### Tabbar Events
 
 | Event | Description                  | Arguments    |

+ 42 - 0
src/packages/__VUE/tabbar/doc.md

@@ -124,6 +124,42 @@ app.use(TabbarItem);
 ```
 :::
 
+### 自定义图标
+通过 icon 插槽自定义图标,可以通过 slot-scope 判断标签是否选中
+
+:::demo
+```html
+<template>
+  <nut-tabbar @tab-switch="tabSwitch">
+    <nut-tabbar-item tab-title="首页">
+      <template #icon="props">
+          <img :src="props.active ? icon.active : icon.unactive" alt="" />
+        </template>
+    </nut-tabbar-item>
+    <nut-tabbar-item tab-title="分类" icon="category"></nut-tabbar-item>
+    <nut-tabbar-item tab-title="发现" icon="find"></nut-tabbar-item>
+  </nut-tabbar>
+</template>
+<script>
+  export default{
+    setup() {
+      function tabSwitch(item, index) {
+        console.log(item, index);
+      }
+      const icon = {
+        active: 'https://img11.360buyimg.com/imagetools/jfs/t1/70423/4/20553/3652/62e74629E23ba550e/aeeed0e3b9f43ae6.png',
+        unactive:'https://img13.360buyimg.com/imagetools/jfs/t1/23319/19/18329/3084/62e7c346E957c54ef/6c3e8a49e52b76f2.png',
+      };
+      return {
+        icon,
+        tabSwitch,
+      };
+    },
+  }
+</script>
+```
+:::
+
 ### 自定义选中
 :::demo
 ```html
@@ -243,6 +279,12 @@ app.use(TabbarItem);
 | placeholder `3.2.6` | 固定在底部时,是否在标签位置生成一个等高的占位元素 | boolean | false |
 
 
+### TabbarItem Slots
+
+| 事件名称   | 说明               | 参数           |
+|------------|--------------------|--------------------|
+| icon | 自定义图标	 | active: boolean |
+
 ### Tabbar Events
 
 | 事件名称   | 说明               | 回调参数           |

+ 4 - 0
src/packages/__VUE/tabbaritem/index.scss

@@ -72,6 +72,10 @@
       display: block;
       background-size: 100% 100%;
       background-position: center center;
+      img {
+        width: 20px;
+        height: 20px;
+      }
     }
     &_nav-word {
       font-size: $tabbar-item-text-font-size;

+ 15 - 5
src/packages/__VUE/tabbaritem/index.taro.vue

@@ -19,7 +19,10 @@
       <template v-if="dot">
         <div class="nut-tabbar-item_icon-box_dot"></div>
       </template>
-      <view v-if="icon">
+      <div class="nut-tabbar-item_icon-box_icon" v-if="isHaveSlot('icon')">
+        <slot name="icon" :active="active"></slot>
+      </div>
+      <view v-if="icon && !isHaveSlot('icon')">
         <nut-icon
           class="nut-tabbar-item_icon-box_icon"
           :size="state.size"
@@ -29,7 +32,7 @@
         ></nut-icon>
       </view>
       <div
-        v-if="!icon && activeImg"
+        v-if="!icon && activeImg && !isHaveSlot('icon')"
         class="nut-tabbar-item_icon-box_icon"
         :style="{
           backgroundImage: `url(${active ? activeImg : img})`,
@@ -38,7 +41,10 @@
         }"
       ></div>
       <view
-        :class="['nut-tabbar-item_icon-box_nav-word', { 'nut-tabbar-item_icon-box_big-word': !icon && !activeImg }]"
+        :class="[
+          'nut-tabbar-item_icon-box_nav-word',
+          { 'nut-tabbar-item_icon-box_big-word': !icon && !activeImg && !isHaveSlot('icon') }
+        ]"
       >
         <view v-if="tabTitle">{{ tabTitle }}</view>
         <slot v-if="!tabTitle"></slot>
@@ -48,7 +54,7 @@
 </template>
 <script lang="ts">
 import { createComponent } from '@/packages/utils/create';
-import { ComponentInternalInstance, computed, getCurrentInstance, inject, onMounted, reactive, watch } from 'vue';
+import { ComponentInternalInstance, computed, getCurrentInstance, inject, reactive, watch } from 'vue';
 const { create } = createComponent('tabbar-item');
 export default create({
   props: {
@@ -97,7 +103,10 @@ export default create({
     },
     to: [Object, String]
   },
-  setup(props, ctx) {
+  setup(props, { emit, slots }) {
+    const isHaveSlot = (slot: string) => {
+      return slots[slot];
+    };
     const parent: any = inject('parent');
     const state = reactive({
       size: parent.size,
@@ -147,6 +156,7 @@ export default create({
     return {
       state,
       active,
+      isHaveSlot,
       change
     };
   }

+ 14 - 5
src/packages/__VUE/tabbaritem/index.vue

@@ -19,8 +19,10 @@
       <template v-if="dot">
         <div class="nut-tabbar-item_icon-box_dot"></div>
       </template>
-
-      <view v-if="icon">
+      <div class="nut-tabbar-item_icon-box_icon" v-if="isHaveSlot('icon')">
+        <slot name="icon" :active="active"></slot>
+      </div>
+      <view v-if="icon && !isHaveSlot('icon')">
         <nut-icon
           class="nut-tabbar-item_icon-box_icon"
           :size="state.size"
@@ -30,7 +32,7 @@
         ></nut-icon>
       </view>
       <div
-        v-if="!icon && activeImg"
+        v-if="!icon && activeImg && !isHaveSlot('icon')"
         class="nut-tabbar-item_icon-box_icon"
         :style="{
           backgroundImage: `url(${active ? activeImg : img})`,
@@ -39,7 +41,10 @@
         }"
       ></div>
       <view
-        :class="['nut-tabbar-item_icon-box_nav-word', { 'nut-tabbar-item_icon-box_big-word': !icon && !activeImg }]"
+        :class="[
+          'nut-tabbar-item_icon-box_nav-word',
+          { 'nut-tabbar-item_icon-box_big-word': !icon && !activeImg && !isHaveSlot('icon') }
+        ]"
       >
         <view v-if="tabTitle">{{ tabTitle }}</view>
         <slot v-if="!tabTitle"></slot>
@@ -99,7 +104,10 @@ export default create({
     },
     to: [Object, String]
   },
-  setup(props, ctx) {
+  setup(props, { emit, slots }) {
+    const isHaveSlot = (slot: string) => {
+      return slots[slot];
+    };
     const parent: any = inject('parent');
     const state = reactive({
       size: parent.size,
@@ -159,6 +167,7 @@ export default create({
     return {
       state,
       active,
+      isHaveSlot,
       change
     };
   }

+ 20 - 0
src/sites/mobile-taro/vue/src/nav/pages/tabbar/index.vue

@@ -36,6 +36,18 @@
         activeImg="http://img14.360buyimg.com/uba/jfs/t1/23967/14/1072/6714/5c0f3d61E0ad8991e/8f741953f6e38f15.jpg"
       ></nut-tabbar-item>
     </nut-tabbar>
+    <h2>自定义图标</h2>
+    <nut-tabbar @tab-switch="tabSwitch">
+      <nut-tabbar-item tab-title="首页1">
+        <template #icon="props">
+          <img v-if="props.active" :src="activeImg" />
+          <img v-else :src="unactiveImg" />
+        </template>
+      </nut-tabbar-item>
+      <nut-tabbar-item tab-title="分类" icon="category"></nut-tabbar-item>
+      <nut-tabbar-item tab-title="发现" icon="find"></nut-tabbar-item>
+    </nut-tabbar>
+
     <h2>自定义选中</h2>
     <nut-tabbar v-model:visible="active" @tab-switch="tabSwitch">
       <nut-tabbar-item tab-title="首页" name="home" icon="home"></nut-tabbar-item>
@@ -88,8 +100,16 @@ export default {
     function tabSwitch(item: object, index: number) {
       console.log(item, index);
     }
+    const activeImg = ref(
+      'https://img11.360buyimg.com/imagetools/jfs/t1/70423/4/20553/3652/62e74629E23ba550e/aeeed0e3b9f43ae6.png'
+    );
+    const unactiveImg = ref(
+      'https://img13.360buyimg.com/imagetools/jfs/t1/23319/19/18329/3084/62e7c346E957c54ef/6c3e8a49e52b76f2.png'
+    );
     return {
       active,
+      activeImg,
+      unactiveImg,
       tabSwitch
     };
   }