Browse Source

feat(swipe): taro funciton test

richard1015 4 years ago
parent
commit
bacf3c6a07

+ 11 - 0
src/config.json

@@ -210,6 +210,17 @@
       "packages": [
         {
           "version": "3.0.0",
+          "name": "Swipe",
+          "taro": true,
+          "type": "component",
+          "cName": "滑动手势操作",
+          "desc": "列表项左滑删除场景使用",
+          "sort": 4,
+          "show": true,
+          "author": "richard1015"
+        },
+        {
+          "version": "3.0.0",
           "name": "ActionSheet",
           "taro": true,
           "sort": "1",

+ 9 - 2
src/packages/__VUE/swipe/demo.vue

@@ -36,7 +36,7 @@
       </template>
     </nut-swipe>
     <h2>异步控制</h2>
-    <nut-swipe ref="refSwipe">
+    <nut-swipe ref="refSwipe" @open="open" @close="close">
       <nut-cell title="异步打开关闭">
         <template v-slot:link>
           <nut-switch
@@ -94,7 +94,14 @@ export default createDemo({
         refSwipe.value?.close();
       }
     };
-    return { checked, number, changSwitch, refSwipe };
+    const open = (obj: any) => {
+      console.log(obj);
+      checked.value = true;
+    };
+    const close = () => {
+      checked.value = false;
+    };
+    return { checked, number, changSwitch, refSwipe, open, close };
   }
 });
 </script>

+ 14 - 7
src/packages/__VUE/swipe/doc.md

@@ -62,7 +62,7 @@ app.use(Swipe);
 ### 异步控制
 
 ``` html
-<nut-swipe ref="refSwipe">
+<nut-swipe ref="refSwipe" @open="open" @close="close">
     <nut-cell title="异步打开关闭">
     <template v-slot:link>
         <nut-switch v-model="checked" @change="changSwitch" active-text="开" inactive-text="关" />
@@ -78,13 +78,20 @@ app.use(Swipe);
         const refSwipe = ref<HTMLElement>();
         const checked = ref(false);
         const changSwitch = (value: boolean) => {
-        if (value) {
-            refSwipe.value?.open('left');
-        } else {
-            refSwipe.value?.close();
-        }
+            if (value) {
+                refSwipe.value?.open('left');
+            } else {
+                refSwipe.value?.close();
+            }
         };
-        return { checked, changSwitch, refSwipe };
+         const open = (obj: any) => {
+            console.log(obj);
+            checked.value = true;
+        };
+        const close = () => {
+            checked.value = false;
+        };
+        return { checked, changSwitch, refSwipe, open, close };
     }
 ```
 

+ 199 - 0
src/packages/__VUE/swipe/index.taro.vue

@@ -0,0 +1,199 @@
+<template>
+  <view
+    :class="classes"
+    :style="touchStyle"
+    @touchstart="onTouchStart"
+    @touchmove="onTouchMove"
+    @touchend="onTouchEnd"
+    @touchcancel="onTouchEnd"
+  >
+    <view class="nut-swipe__left" ref="leftRef" :id="'leftRef-' + refRandomId">
+      <slot name="left"></slot>
+    </view>
+
+    <view class="nut-swipe__content">
+      <slot name="default"></slot>
+    </view>
+
+    <view
+      class="nut-swipe__right"
+      ref="rightRef"
+      :id="'rightRef-' + refRandomId"
+    >
+      <slot name="right"></slot>
+    </view>
+  </view>
+</template>
+<script lang="ts">
+import Taro from '@tarojs/taro';
+import { useTouch } from '../../utils/useTouch';
+import { computed, nextTick, onMounted, reactive, Ref, ref } from 'vue';
+import { createComponent } from '../../utils/create';
+import { useTaroRect } from '../../utils/useTaroRect';
+const { componentName, create } = createComponent('swipe');
+export type SwipePosition = 'left' | 'right' | '';
+export default create({
+  props: {
+    name: {
+      type: String,
+      default: ''
+    },
+    disabled: {
+      type: Boolean,
+      default: false
+    }
+  },
+  emits: ['open', 'close'],
+
+  setup(props, { emit }) {
+    const refRandomId = Math.random().toString(36).slice(-8);
+    const classes = computed(() => {
+      const prefixCls = componentName;
+      return {
+        [prefixCls]: true
+      };
+    });
+
+    const getRefWidth = async (ref: Ref<HTMLElement | undefined>) => {
+      let rect = await useTaroRect(ref, Taro);
+      return rect.width || 0;
+    };
+
+    const leftRef = ref<HTMLElement>();
+    const leftRefWidth = ref(0);
+    const rightRef = ref<HTMLElement>();
+    const rightRefWidth = ref(0);
+
+    const initWidth = async () => {
+      leftRefWidth.value = await getRefWidth(leftRef);
+      rightRefWidth.value = await getRefWidth(rightRef);
+    };
+
+    onMounted(async () => {
+      setTimeout(async () => {
+        await initWidth();
+      }, 300);
+    });
+
+    let opened: boolean = false;
+    let position: SwipePosition = '';
+    let oldPosition: SwipePosition = '';
+
+    const state = reactive({
+      offset: 0,
+      moving: false
+    });
+
+    const open = (p: SwipePosition = '') => {
+      opened = true;
+      if (p) {
+        state.offset = p === 'left' ? -rightRefWidth.value : leftRefWidth.value;
+      }
+      emit('open', {
+        name: props.name,
+        position: position || p
+      });
+    };
+
+    const close = () => {
+      state.offset = 0;
+      opened = false;
+      emit('close', {
+        name: props.name,
+        position
+      });
+    };
+
+    const touchStyle = computed(() => {
+      return {
+        transform: `translate3d(${state.offset}px, 0, 0)`
+      };
+    });
+
+    const setoffset = (deltaX: number) => {
+      position = deltaX > 0 ? 'right' : 'left';
+      let offset = deltaX;
+      switch (position) {
+        case 'left':
+          if (opened && oldPosition === position) {
+            offset = -rightRefWidth.value;
+          } else {
+            offset =
+              Math.abs(deltaX) > rightRefWidth.value
+                ? -rightRefWidth.value
+                : deltaX;
+          }
+          break;
+        case 'right':
+          if (opened && oldPosition === position) {
+            offset = leftRefWidth.value;
+          } else {
+            offset =
+              Math.abs(deltaX) > leftRefWidth.value
+                ? leftRefWidth.value
+                : deltaX;
+          }
+          break;
+      }
+      state.offset = offset;
+    };
+
+    const touch = useTouch();
+    const touchMethods = {
+      onTouchStart(event: Event) {
+        if (props.disabled) return;
+        touch.start(event);
+      },
+      async onTouchMove(event: Event) {
+        if (props.disabled) return;
+        if (touch.isVertical()) return;
+        await initWidth();
+        state.moving = true;
+        touch.move(event);
+        setoffset(touch.deltaX.value);
+
+        event.preventDefault();
+      },
+      onTouchEnd() {
+        if (state.moving) {
+          state.moving = false;
+          oldPosition = position;
+          switch (position) {
+            case 'left':
+              if (Math.abs(state.offset) <= rightRefWidth.value / 2) {
+                close();
+              } else {
+                state.offset = -rightRefWidth.value;
+                open();
+              }
+              break;
+            case 'right':
+              if (Math.abs(state.offset) <= leftRefWidth.value / 2) {
+                close();
+              } else {
+                state.offset = leftRefWidth.value;
+                open();
+              }
+              break;
+          }
+        }
+      }
+    };
+
+    return {
+      classes,
+      touchStyle,
+      ...touchMethods,
+      leftRef,
+      rightRef,
+      refRandomId,
+      open,
+      close
+    };
+  }
+});
+</script>
+
+<style lang="scss">
+@import 'index.scss';
+</style>

+ 12 - 24
src/packages/__VUE/swipe/index.vue

@@ -1,6 +1,5 @@
 <template>
   <view
-    ref="swipeRef"
     :class="classes"
     :style="touchStyle"
     @touchstart="onTouchStart"
@@ -52,10 +51,7 @@ export default create({
     const getRefWidth = (ref: Ref<HTMLElement | undefined>): number => {
       return ref.value?.clientWidth || 0;
     };
-    const swipeRef = ref<HTMLElement>(),
-      swipeRefWidth = computed(() => {
-        return getRefWidth(swipeRef);
-      });
+
     const leftRef = ref<HTMLElement>(),
       leftRefWidth = computed(() => {
         return getRefWidth(leftRef);
@@ -64,9 +60,6 @@ export default create({
       rightRefWidth = computed(() => {
         return getRefWidth(rightRef);
       });
-    const touchMaxWidth = computed(() => {
-      return rightRefWidth.value + +rightRefWidth.value;
-    });
 
     let opened: boolean = false;
     let position: SwipePosition = '';
@@ -77,28 +70,24 @@ export default create({
       moving: false
     });
 
-    const open = (position: SwipePosition = '') => {
+    const open = (p: SwipePosition = '') => {
       opened = true;
-      if (position) {
-        state.offset =
-          position === 'left' ? -rightRefWidth.value : leftRefWidth.value;
+      if (p) {
+        state.offset = p === 'left' ? -rightRefWidth.value : leftRefWidth.value;
       }
       emit('open', {
         name: props.name,
-        position
+        position: position || p
       });
     };
 
     const close = () => {
       state.offset = 0;
-
-      if (opened) {
-        opened = false;
-        emit('close', {
-          name: props.name,
-          position
-        });
-      }
+      opened = false;
+      emit('close', {
+        name: props.name,
+        position
+      });
     };
 
     const touchStyle = computed(() => {
@@ -156,7 +145,7 @@ export default create({
           oldPosition = position;
           switch (position) {
             case 'left':
-              if (Math.abs(state.offset) < rightRefWidth.value / 2) {
+              if (Math.abs(state.offset) <= rightRefWidth.value / 2) {
                 close();
               } else {
                 state.offset = -rightRefWidth.value;
@@ -164,7 +153,7 @@ export default create({
               }
               break;
             case 'right':
-              if (Math.abs(state.offset) < leftRefWidth.value / 2) {
+              if (Math.abs(state.offset) <= leftRefWidth.value / 2) {
                 close();
               } else {
                 state.offset = leftRefWidth.value;
@@ -182,7 +171,6 @@ export default create({
       ...touchMethods,
       leftRef,
       rightRef,
-      swipeRef,
       open,
       close
     };

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

@@ -8,6 +8,7 @@ export default {
     {
       root: 'feedback',
       pages: [
+        'pages/swipe/index',
         'pages/collapse/index',
         'pages/backtop/index',
         'pages/actionsheet/index',

+ 3 - 0
src/sites/mobile-taro/vue/src/feedback/pages/swipe/index.config.ts

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

+ 107 - 0
src/sites/mobile-taro/vue/src/feedback/pages/swipe/index.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="demo full">
+    <h2>基础用法</h2>
+    <nut-swipe>
+      <nut-cell round-radius="0" desc="左滑删除" />
+      <template #right>
+        <nut-button shape="square" style="height: 100%" type="danger"
+          >删除</nut-button
+        >
+      </template>
+    </nut-swipe>
+    <h2>禁止滑动</h2>
+    <nut-swipe disabled>
+      <nut-cell round-radius="0" desc="禁止滑动" />
+      <template #right>
+        <nut-button shape="square" style="height: 100%" type="danger"
+          >删除</nut-button
+        >
+      </template>
+    </nut-swipe>
+    <h2>左右滑动</h2>
+    <nut-swipe>
+      <template #left>
+        <nut-button shape="square" style="height: 100%" type="success"
+          >选择</nut-button
+        >
+      </template>
+      <nut-cell round-radius="0" desc="左滑右滑都可以哦" />
+      <template #right>
+        <nut-button shape="square" style="height: 100%" type="danger"
+          >删除</nut-button
+        >
+        <nut-button shape="square" style="height: 100%" type="info"
+          >收藏</nut-button
+        >
+      </template>
+    </nut-swipe>
+    <h2>异步控制</h2>
+    <nut-swipe ref="refSwipe" @open="open" @close="close">
+      <nut-cell title="异步打开关闭">
+        <template v-slot:link>
+          <nut-switch
+            v-model="checked"
+            @change="changSwitch"
+            active-text="开"
+            inactive-text="关"
+          />
+        </template>
+      </nut-cell>
+      <template #right>
+        <nut-button shape="square" style="height: 100%" type="danger"
+          >删除</nut-button
+        >
+      </template>
+    </nut-swipe>
+    <h2>自定义</h2>
+    <nut-swipe>
+      <template #left>
+        <nut-button shape="square" style="height: 100%" type="success"
+          >选择</nut-button
+        >
+      </template>
+      <nut-cell title="商品描述">
+        <template v-slot:link>
+          <nut-inputnumber v-model="number" />
+        </template>
+      </nut-cell>
+      <template #right>
+        <nut-button shape="square" style="height: 100%" type="danger"
+          >删除</nut-button
+        >
+        <nut-button shape="square" style="height: 100%" type="info"
+          >收藏</nut-button
+        >
+      </template>
+    </nut-swipe>
+  </div>
+</template>
+
+<script lang="ts">
+import { ref } from 'vue';
+export default {
+  props: {},
+  setup() {
+    const refSwipe = ref<HTMLElement>();
+    const checked = ref(false);
+    const number = ref(0);
+    const changSwitch = (value: boolean) => {
+      if (value) {
+        refSwipe.value?.open('left');
+      } else {
+        refSwipe.value?.close();
+      }
+    };
+    const open = (obj: any) => {
+      console.log(obj);
+      checked.value = true;
+    };
+    const close = () => {
+      checked.value = false;
+    };
+    return { checked, number, changSwitch, refSwipe, open, close };
+  }
+};
+</script>
+
+<style lang="scss" scoped></style>