Browse Source

test(tab): taro 适配测试

richard1015 4 years ago
parent
commit
3988ca84e0

+ 2 - 1
src/config.json

@@ -438,6 +438,7 @@
           "cName": "标签组件",
           "type": "component",
           "show": true,
+          "taro": true,
           "desc": "标签组件",
           "author": "zhenyulei"
         },
@@ -446,7 +447,7 @@
           "sort": 2,
           "cName": "标签组件",
           "type": "component",
-          "show": true,
+          "show": false,
           "desc": "标签组件",
           "author": "zhenyulei"
         },

+ 176 - 0
src/packages/__VUE/tab/index.taro.vue

@@ -0,0 +1,176 @@
+<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>
+      </view>
+      <view class="underline"></view>
+    </view>
+    <nut-swiper
+      :init-page="defaultIndex"
+      :pagination-visible="false"
+      :duration="animatedTime"
+      pagination-color="#426543"
+      @change="changeTab"
+      ref="nutuiSwiper"
+      :touchable="!noSwiping"
+      :direction="direction"
+      class="tab-swiper"
+    >
+      <slot></slot>
+    </nut-swiper>
+  </view>
+</template>
+<script lang="ts">
+import { PropType, reactive, ref, onMounted, watch, VNode } from 'vue';
+import { createComponent } from '../../utils/create';
+import tabpanel from '../../__VUE/tabpanel/index.vue';
+const { create } = createComponent('tab');
+import TabTitle from './tabTitle';
+type TabDirection = 'horizontal' | 'vertical';
+
+interface DataTitle {
+  title?: string;
+  content?: VNode[];
+}
+
+type currChild = {
+  header: Function;
+} & VNode[];
+
+export default create({
+  children: [tabpanel],
+  props: {
+    defaultIndex: {
+      type: Number,
+      default: 0
+    },
+    animatedTime: {
+      type: Number,
+      default: 0
+    },
+    direction: {
+      type: String as PropType<TabDirection>,
+      default: 'horizontal'
+    },
+    noSwiping: {
+      type: Boolean,
+      default: false
+    },
+    scrollType: {
+      type: String,
+      default: 'flex'
+    }
+  },
+  components: {
+    TabTitle
+  },
+  setup(props, ctx) {
+    const titles: Array<DataTitle> = reactive([]);
+    const isLock = ref(false);
+    const activeIndex = ref(props.defaultIndex);
+    const navlist = ref<null | HTMLElement>(null);
+    const nutuiSwiper = ref(null);
+    // 生成随机的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);
+        }
+      }
+    }
+    const changeTab = (index: number) => {
+      console.log(index);
+      activeIndex.value = index;
+      centerTitle(index);
+
+      //
+    };
+    //切换tab
+    function switchTitle(index: number) {
+      activeIndex.value = index;
+      centerTitle(index);
+      console.log(nutuiSwiper.value);
+      nutuiSwiper.value.to(index);
+    }
+    function initTitle() {
+      titles.length = 0;
+      if (ctx.slots.default) {
+        const slots: VNode[] =
+          ctx.slots.default().length === 1
+            ? (ctx.slots.default()[0].children as VNode[])
+            : ctx.slots.default();
+        slots &&
+          slots.map((item, index) => {
+            if (typeof item.children == 'string') return;
+            titles.push({
+              title:
+                item.props && item.props['tab-title']
+                  ? item.props['tab-title']
+                  : '',
+              content:
+                item.children && (item.children as currChild).header
+                  ? (item.children as currChild).header()
+                  : null
+            });
+          });
+      }
+    }
+    onMounted(() => {
+      initTitle();
+    });
+    watch(
+      () => (ctx.slots.default ? ctx.slots.default() : ''),
+      () => {
+        initTitle();
+      }
+    );
+    return {
+      swiperClassName,
+      titles,
+      navlist,
+      activeIndex,
+      switchTitle,
+      changeTab,
+      nutuiSwiper
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 3 - 2
src/sites/mobile-taro/vue/config/index.js

@@ -1,4 +1,5 @@
 const path = require('path');
+console.log(path.resolve(__dirname, '../../../../../node_modules/@vue'));
 const config = {
   projectName: '@nutui/nutui-taro-mobile',
   date: '2021-5-29',
@@ -13,8 +14,8 @@ const config = {
     webpackChain(chain, webpack) {
       chain.merge({
         alias: {
-          '@vue': path.resolve(__dirname, '../node_modules/@vue'),
-          vue: path.resolve(__dirname, '../node_modules/@vue')
+          '@vue': path.resolve(__dirname, '../../../../../node_modules/@vue'),
+          vue: path.resolve(__dirname, '../../../../../node_modules/@vue')
         },
         runtime: {
           enableSizeAPIs: true

+ 1 - 1
src/sites/mobile-taro/vue/src/app.config.ts

@@ -34,7 +34,7 @@ export default {
     },
     {
       root: 'nav',
-      pages: ['pages/navbar/index', 'pages/tabbar/index']
+      pages: ['pages/navbar/index', 'pages/tabbar/index', 'pages/tab/index']
     },
     {
       root: 'dentry',

+ 3 - 0
src/sites/mobile-taro/vue/src/nav/pages/tab/index.config.ts

@@ -0,0 +1,3 @@
+export default {
+  navigationBarTitleText: 'Tab'
+};

+ 195 - 0
src/sites/mobile-taro/vue/src/nav/pages/tab/index.vue

@@ -0,0 +1,195 @@
+<template>
+  <div class="demo full">
+    <h2>基础用法,默认tab-title宽度均分相等</h2>
+    <nut-tab>
+      <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>defaultIndex设置默认显示tab</h2>
+    <h2>switchTab监听切换tab返回事件</h2>
+    <nut-tab :default-index="1" @switch-tab="switchTab">
+      <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> animatedTime 开启切换标签内容时的转场动画时间</h2>
+    <nut-tab :animated-time="500">
+      <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> 禁止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
+    >
+    <nut-tab :animated-time="500" scrollType="scroll">
+      <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-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>设置slot:header可以自定义标签</h2>
+    <nut-tab scrollType="scroll">
+      <nut-tab-panel tab-title="全部">
+        <template v-slot:header><nut-icon name="dongdong"></nut-icon></template>
+        <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-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>左右tab布局</h2>
+    <nut-tab
+      direction="vertical"
+      :animated-time="500"
+      :default-index="2"
+      scrollType="scroll"
+    >
+      <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-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>异步操作</h2>
+    <nut-tab :animated-time="500" v-if="editList.length > 0">
+      <nut-tab-panel
+        :tab-title="item.title"
+        v-for="(item, index) in editList"
+        :key="index"
+      >
+        <p class="content">这里是页签{{ index }}内容</p>
+      </nut-tab-panel>
+    </nut-tab>
+    <nut-button type="primary" @click="changeList">改变数据</nut-button>
+  </div>
+</template>
+
+<script lang="ts">
+import { ref, reactive, toRefs } from 'vue';
+export default {
+  props: {},
+  setup() {
+    const resData = reactive({
+      editList: [
+        {
+          title: '标签一'
+        },
+        {
+          title: '标签二'
+        }
+      ]
+    });
+    function changeList() {
+      resData.editList.push({
+        title: '标签' + resData.editList.length
+      });
+    }
+    function switchTab(activeInddex: number, event: MouseEvent) {
+      console.log(activeInddex, event);
+    }
+    return {
+      ...toRefs(resData),
+      changeList,
+      switchTab
+    };
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.content {
+  padding: 10px;
+}
+</style>