ソースを参照

fix: tab组件兼容taro (#552)

zhenyulei 4 年 前
コミット
b294f38a9e

+ 3 - 2
src/packages/__VUE/tab/demo.vue

@@ -16,9 +16,9 @@
       >
     </nut-tab>
 
-    <h2>defaultIndex设置默认显示tab</h2>
+    <h2>defaultIndex设置默认显示tab,iconType为half时切换选中icon样式</h2>
     <h2>switchTab监听切换tab返回事件</h2>
-    <nut-tab :default-index="1" @switch-tab="switchTab">
+    <nut-tab :default-index="1" @switch-tab="switchTab" icon-type="half">
       <nut-tab-panel tab-title="全部"
         ><p class="content">这里是页签全部内容</p></nut-tab-panel
       >
@@ -118,6 +118,7 @@
       :animated-time="500"
       :default-index="2"
       scrollType="scroll"
+      icon-type="half"
     >
       <nut-tab-panel tab-title="页签一"
         ><p class="content">这里是页签一内容</p></nut-tab-panel

+ 83 - 2
src/packages/__VUE/tab/index.scss

@@ -1,5 +1,5 @@
 .nutui-tab {
-  .tab-title {
+  .tab-title-scroll {
     width: 100%;
     height: 46px;
     overflow-x: scroll;
@@ -7,6 +7,15 @@
     flex-wrap: nowrap;
     scroll-behavior: smooth;
     background: #f5f5f5;
+  }
+  .tab-title {
+    width: 100%;
+    height: 46px;
+    display: flex;
+    flex-direction: row;
+    flex-wrap: nowrap;
+    scroll-behavior: smooth;
+    background: #f5f5f5;
     position: relative;
     &::-webkit-scrollbar {
       display: none;
@@ -45,6 +54,34 @@
       }
     }
   }
+  .tab-title-scroll {
+    overflow-x: scroll;
+  }
+  .half {
+    .nut-tab-active {
+      color: #1a1a1a;
+      font-weight: bold;
+      font-size: 16px;
+      position: relative;
+      &::after {
+        content: '';
+        display: none;
+      }
+      .world {
+        position: relative;
+        &::after {
+          content: '';
+          position: absolute;
+          right: -8px;
+          bottom: -5px;
+          width: 11px;
+          height: 10px;
+          background-image: url('https://img12.360buyimg.com/imagetools/jfs/t1/197875/38/105/620/60ffcd30E34877e77/54c3dd9fe0a5ab76.png');
+          background-size: 100% 100%;
+        }
+      }
+    }
+  }
   .tab-swiper {
     overflow: hidden;
     display: block;
@@ -57,12 +94,19 @@
 .vertical-tab {
   display: flex;
   height: 175px;
+  .tab-title-scroll {
+    width: 100px;
+    height: 175px;
+    display: flex;
+    flex-wrap: nowrap;
+    scroll-behavior: smooth;
+    background: #f5f5f5;
+  }
   .tab-title {
     width: 100px;
     height: 100%;
     display: flex;
     flex-direction: column;
-    overflow-y: scroll;
     &::-webkit-scrollbar {
       display: none;
     }
@@ -97,6 +141,34 @@
       }
     }
   }
+  .tab-title-scroll {
+    overflow-y: scroll;
+  }
+  .half {
+    .nut-tab-active {
+      color: #1a1a1a;
+      font-weight: bold;
+      font-size: 16px;
+      position: relative;
+      &::after {
+        content: '';
+        display: none;
+      }
+      .world {
+        position: relative;
+        &::after {
+          content: '';
+          position: absolute;
+          right: -15px;
+          bottom: -5px;
+          width: 11px;
+          height: 10px;
+          background-image: url('https://img12.360buyimg.com/imagetools/jfs/t1/197875/38/105/620/60ffcd30E34877e77/54c3dd9fe0a5ab76.png');
+          background-size: 100% 100%;
+        }
+      }
+    }
+  }
   .tab-swiper {
     overflow: hidden;
     display: block;
@@ -106,3 +178,12 @@
     box-sizing: border-box;
   }
 }
+
+.horize {
+  display: flex;
+  flex-direction: row;
+  flex-wrap: nowrap;
+}
+.content {
+  padding: 10px;
+}

+ 90 - 49
src/packages/__VUE/tab/index.taro.vue

@@ -1,31 +1,42 @@
 <template>
   <view :class="[direction === 'vertical' ? 'vertical-tab' : 'nutui-tab']">
-    <view class="tab-title" ref="navlist">
-      <view
-        :class="[
-          'tab-title-box',
-          { 'nut-tab-active': activeIndex == index },
-          { 'tab-title-box-scroll': scrollType == 'scroll' }
-        ]"
-        v-for="(item, index) in titles"
-        :key="index"
-        @click="switchTitle(index, $event)"
-      >
-        {{ item.title }}
-        <TabTitle v-bind:slots="item.content" v-if="item.content"></TabTitle>
+    <scroll-view
+      :scroll-x="!scrollYDirection"
+      :scroll-y="scrollYDirection"
+      :scroll-left="scrollLeft"
+      :scroll-top="scrollTop"
+      class="tab-title-scroll"
+      :scroll-with-animation="true"
+    >
+      <view :class="['tab-title', randomTitleClass, iconType]">
+        <view
+          :class="[
+            'tab-title-box',
+            randomClass,
+            { 'nut-tab-active': activeIndex == index },
+            { 'tab-title-box-scroll': scrollType == 'scroll' }
+          ]"
+          v-for="(item, index) in titles"
+          :key="index"
+          @click="switchTitle(index, $event)"
+        >
+          <span class="world">{{ item.title }}</span>
+          <TabTitle v-bind:slots="item.content" v-if="item.content"></TabTitle>
+        </view>
+        <view class="underline"></view>
       </view>
-      <view class="underline"></view>
-    </view>
+    </scroll-view>
     <nut-swiper
-      :init-page="defaultIndex"
+      :current="activeIndex"
       :pagination-visible="false"
       :duration="animatedTime"
       pagination-color="#426543"
-      @change="changeTab"
+      @change="(current) => changeTab(current)"
       ref="nutuiSwiper"
       :touchable="!noSwiping"
-      :direction="direction"
+      :vertical="scrollYDirection"
       class="tab-swiper"
+      :circular="true"
     >
       <slot></slot>
     </nut-swiper>
@@ -34,8 +45,9 @@
 <script lang="ts">
 import { PropType, reactive, ref, onMounted, watch, VNode } from 'vue';
 import { createComponent } from '../../utils/create';
-import tabpanel from '../../__VUE/tabpanel/index.vue';
+import tabpanel from '../../__VUE/tabpanel/index.taro.vue';
 const { create } = createComponent('tab');
+import Taro from '@tarojs/taro';
 import TabTitle from './tabTitle';
 type TabDirection = 'horizontal' | 'vertical';
 
@@ -61,7 +73,7 @@ export default create({
     },
     direction: {
       type: String as PropType<TabDirection>,
-      default: 'horizontal'
+      default: 'false'
     },
     noSwiping: {
       type: Boolean,
@@ -70,6 +82,10 @@ export default create({
     scrollType: {
       type: String,
       default: 'flex'
+    },
+    iconType: {
+      type: String,
+      default: 'all'
     }
   },
   components: {
@@ -78,53 +94,69 @@ export default create({
   setup(props, ctx) {
     const titles: Array<DataTitle> = reactive([]);
     const isLock = ref(false);
+    const scrollLeft = ref('0px');
+    const scrollTop = ref('0px');
     const activeIndex = ref(props.defaultIndex);
     const navlist = ref<null | HTMLElement>(null);
     const nutuiSwiper = ref(null);
+    const arr = ref([]);
+    const scrollYDirection = ref(props.direction === 'vertical');
+    const randomClass = ref('tab-title-boxs-' + createHash());
+    const randomTitleClass = ref('tab-title-' + createHash());
     // 生成随机的id
     function createHash() {
       return Array.from(Array(10), () =>
         Math.floor(Math.random() * 36).toString(36)
       ).join('');
     }
-
     const swiperClassName = ref('swiper-' + createHash());
     //title点击后居中显示
     function centerTitle(index: number) {
-      if (navlist.value) {
-        const currEle = navlist.value.querySelectorAll('.tab-title-box')[
-          index
-        ] as HTMLElement;
-        if (props.direction === 'vertical') {
-          const currTitleTop = navlist.value.offsetTop;
-          const currTop = currEle.offsetTop;
-          const currHeight = currEle.offsetHeight;
-          const tapHeight = navlist.value.offsetHeight;
-          navlist.value.scroll(
-            0,
-            currTop - currTitleTop - tapHeight / 2 + currHeight / 2
-          );
-        } else {
-          const currLeft = currEle.offsetLeft;
-          const currWidth = currEle.offsetWidth;
-          const tapWidth = navlist.value.offsetWidth;
-          navlist.value.scroll(currLeft - tapWidth / 2 + currWidth / 2, 0);
-        }
+      let navlistValueTop = 0;
+      let navlistValueHeight = 0;
+      let navlistValuewidth = 0;
+      const query = Taro.createSelectorQuery();
+      if (props.direction === 'vertical') {
+        query
+          .select(`.${randomTitleClass.value}`)
+          .boundingClientRect()
+          .selectAll(`.${randomClass.value}`)
+          .boundingClientRect()
+          .exec((rects) => {
+            let navlistValueTop = rects[0].top;
+            let navlistValueHeight = rects[0].height;
+            const currTop = rects[1][index].top;
+            const currHeight = rects[1][index].height;
+            scrollTop.value =
+              currTop -
+              navlistValueTop -
+              navlistValueHeight / 2 +
+              currHeight / 2 +
+              'px';
+          });
+      } else {
+        query
+          .select(`.${randomTitleClass.value}`)
+          .boundingClientRect()
+          .selectAll(`.${randomClass.value}`)
+          .boundingClientRect()
+          .exec((rects) => {
+            let navlistValuewidth = rects[0].width;
+            const currLeft = rects[1][index].left;
+            const currWidth = rects[1][index].width;
+            scrollLeft.value =
+              currLeft - navlistValuewidth / 2 + currWidth / 2 + 'px';
+          });
       }
     }
-    const changeTab = (index: number) => {
-      console.log(index);
-      activeIndex.value = index;
-      centerTitle(index);
-
-      //
+    const changeTab = (current) => {
+      activeIndex.value = current.detail.current;
+      centerTitle(current.detail.current);
     };
     //切换tab
     function switchTitle(index: number) {
       activeIndex.value = index;
       centerTitle(index);
-      console.log(nutuiSwiper.value);
-      nutuiSwiper.value.to(index);
     }
     function initTitle() {
       titles.length = 0;
@@ -151,6 +183,9 @@ export default create({
     }
     onMounted(() => {
       initTitle();
+      let arrnew = [];
+      for (let i = 0; i < 100; i++) arrnew.push(i);
+      arr.value = arrnew;
     });
     watch(
       () => (ctx.slots.default ? ctx.slots.default() : ''),
@@ -165,7 +200,13 @@ export default create({
       activeIndex,
       switchTitle,
       changeTab,
-      nutuiSwiper
+      nutuiSwiper,
+      scrollLeft,
+      scrollTop,
+      arr,
+      randomClass,
+      scrollYDirection,
+      randomTitleClass
     };
   }
 });

+ 6 - 2
src/packages/__VUE/tab/index.vue

@@ -1,6 +1,6 @@
 <template>
   <view :class="[direction === 'vertical' ? 'vertical-tab' : 'nutui-tab']">
-    <view class="tab-title" ref="navlist">
+    <view :class="['tab-title', iconType, 'tab-title-scroll']" ref="navlist">
       <view
         :class="[
           'tab-title-box',
@@ -11,7 +11,7 @@
         :key="index"
         @click="switchTitle(index, $event)"
       >
-        {{ item.title }}
+        <span class="world">{{ item.title }}</span>
         <TabTitle v-bind:slots="item.content" v-if="item.content"></TabTitle>
       </view>
       <view class="underline"></view>
@@ -70,6 +70,10 @@ export default create({
     scrollType: {
       type: String,
       default: 'flex'
+    },
+    iconType: {
+      type: String,
+      default: 'all'
     }
   },
   components: {

+ 26 - 0
src/packages/__VUE/tabpanel/index.taro.vue

@@ -0,0 +1,26 @@
+<template>
+  <nut-swiper-item>
+    <slot></slot>
+  </nut-swiper-item>
+</template>
+<script lang="ts">
+import { createComponent } from '../../utils/create';
+const { create } = createComponent('tab-panel');
+
+export default create({
+  props: {
+    tabTitle: {
+      type: String,
+      default: ''
+    }
+  },
+
+  setup(props, ctx) {
+    //
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 2 - 18
src/sites/mobile-taro/vue/src/nav/pages/tab/index.vue

@@ -16,9 +16,9 @@
       >
     </nut-tab>
 
-    <h2>defaultIndex设置默认显示tab</h2>
+    <h2>defaultIndex设置默认显示tab,iconType为half时切换选中icon样式</h2>
     <h2>switchTab监听切换tab返回事件</h2>
-    <nut-tab :default-index="1" @switch-tab="switchTab">
+    <nut-tab :default-index="1" @switch-tab="switchTab" icon-type="half">
       <nut-tab-panel tab-title="全部"
         ><p class="content">这里是页签全部内容</p></nut-tab-panel
       >
@@ -49,22 +49,6 @@
       >
     </nut-tab>
 
-    <h2> 禁止tab内容滑动</h2>
-    <nut-tab :no-swiping="true">
-      <nut-tab-panel tab-title="全部"
-        ><p class="content">这里是页签全部内容</p></nut-tab-panel
-      >
-      <nut-tab-panel tab-title="待付款"
-        ><p class="content">这里是页签待付款内容</p></nut-tab-panel
-      >
-      <nut-tab-panel tab-title="待收获"
-        ><p class="content">这里是页签待收获内容</p></nut-tab-panel
-      >
-      <nut-tab-panel tab-title="已完成"
-        ><p class="content">这里是页签已完成内容</p></nut-tab-panel
-      >
-    </nut-tab>
-
     <h2>
       设置scrollType="scroll",标签栏可以在水平方向上滚动,切换时会自动将当前标签居中。</h2
     >