quanyawei
2023-10-20 d8b41fff43a2cee6a8f714ffa807623b15803786
uni_modules/uview-ui/components/u-swipe-action-item/u-swipe-action-item.vue
New file
@@ -0,0 +1,190 @@
<template>
   <view class="u-swipe-action-item" ref="u-swipe-action-item">
      <view class="u-swipe-action-item__right">
         <slot name="button">
            <view v-for="(item,index) in options" :key="index" class="u-swipe-action-item__right__button"
               :ref="`u-swipe-action-item__right__button-${index}`" :style="[{
                  alignItems: item.style && item.style.borderRadius ? 'center' : 'stretch'
               }]" @tap="buttonClickHandler(item, index)">
               <view class="u-swipe-action-item__right__button__wrapper" :style="[{
                     backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
                     borderRadius: item.style && item.style.borderRadius ? item.style.borderRadius : '0',
                     padding: item.style && item.style.borderRadius ? '0' : '0 15px',
                  }, item.style]">
                  <u-icon v-if="item.icon" :name="item.icon"
                     :color="item.style && item.style.color ? item.style.color : '#ffffff'"
                     :size="item.iconSize ? $u.addUnit(item.iconSize) : item.style && item.style.fontSize ? $u.getPx(item.style.fontSize) * 1.2 : 17"
                     :customStyle="{
                        marginRight: item.text ? '2px' : 0
                     }"></u-icon>
                  <text v-if="item.text" class="u-swipe-action-item__right__button__wrapper__text u-line-1"
                     :style="[{
                        color: item.style && item.style.color ? item.style.color : '#ffffff',
                        fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px',
                        lineHeight: item.style && item.style.fontSize ? item.style.fontSize : '16px',
                     }]">{{ item.text }}</text>
               </view>
            </view>
         </slot>
      </view>
      <!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ -->
      <view class="u-swipe-action-item__content" @touchstart="wxs.touchstart" @touchmove="wxs.touchmove"
         @touchend="wxs.touchend" :status="status" :change:status="wxs.statusChange" :size="size"
         :change:size="wxs.sizeChange">
         <!-- #endif -->
         <!-- #ifdef APP-NVUE -->
         <view class="u-swipe-action-item__content" ref="u-swipe-action-item__content" @panstart="onTouchstart"
            @tap="clickHandler">
            <!-- #endif -->
            <slot />
         </view>
      </view>
</template>
<!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ -->
<script src="./index.wxs" module="wxs" lang="wxs"></script>
<!-- #endif -->
<script>
   import touch from '../../libs/mixin/touch.js'
   import props from './props.js';
   // #ifdef APP-NVUE
   import nvue from './nvue.js';
   // #endif
   // #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
   import wxs from './wxs.js';
   // #endif
   /**
    * SwipeActionItem 滑动单元格子组件
    * @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
    * @tutorial https://www.uviewui.com/components/swipeAction.html
    * @property {Boolean}         show         控制打开或者关闭(默认 false )
    * @property {String | Number}   index         标识符,如果是v-for,可用index索引
    * @property {Boolean}         disabled      是否禁用(默认 false )
    * @property {Boolean}         autoClose      是否自动关闭其他swipe按钮组(默认 true )
    * @property {Number}         threshold      滑动距离阈值,只有大于此值,才被认为是要打开菜单(默认 30 )
    * @property {Array}         options         右侧按钮内容
    * @property {String | Number}   duration      动画过渡时间,单位ms(默认 350 )
    * @event {Function(index)}   open   组件打开时触发
    * @event {Function(index)}   close   组件关闭时触发
    * @example   <u-swipe-action><u-swipe-action-item :options="options1" ></u-swipe-action-item></u-swipe-action>
    */
   export default {
      name: 'u-swipe-action-item',
      mixins: [uni.$u.mpMixin, uni.$u.mixin, props, touch],
      // #ifdef APP-NVUE
      mixins: [uni.$u.mpMixin, uni.$u.mixin, props, nvue, touch],
      // #endif
      // #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
      mixins: [uni.$u.mpMixin, uni.$u.mixin, props, touch, wxs],
      // #endif
      data() {
         return {
            // 按钮的尺寸信息
            size: {},
            // 父组件u-swipe-action的参数
            parentData: {
               autoClose: true,
            },
            // 当前状态,open-打开,close-关闭
            status: 'close',
         }
      },
      watch: {
         // 由于wxs无法直接读取外部的值,需要在外部值变化时,重新执行赋值逻辑
         wxsInit(newValue, oldValue) {
            this.queryRect()
         }
      },
      computed: {
         wxsInit() {
            return [this.disabled, this.autoClose, this.threshold, this.options, this.duration]
         }
      },
      mounted() {
         this.init()
      },
      methods: {
         init() {
            // 初始化父组件数据
            this.updateParentData()
            // #ifndef APP-NVUE
            uni.$u.sleep().then(() => {
               this.queryRect()
            })
            // #endif
         },
         updateParentData() {
            // 此方法在mixin中
            this.getParentData('u-swipe-action')
         },
         // #ifndef APP-NVUE
         // 查询节点
         queryRect() {
            this.$uGetRect('.u-swipe-action-item__right__button', true).then(buttons => {
               this.size = {
                  buttons,
                  show: this.show,
                  disabled: this.disabled,
                  threshold: this.threshold,
                  duration: this.duration
               }
            })
         },
         // #endif
         // 按钮被点击
         buttonClickHandler(item, index) {
            this.$emit('click', {
               index,
               name: this.name
            })
         }
      },
   }
</script>
<style lang="scss" scoped>
   @import "../../libs/css/components.scss";
   .u-swipe-action-item {
      position: relative;
      overflow: hidden;
      /* #ifndef APP-NVUE || MP-WEIXIN */
      touch-action: pan-y;
      /* #endif */
      &__content {
         background-color: #FFFFFF;
         z-index: 10;
      }
      &__right {
         position: absolute;
         top: 0;
         bottom: 0;
         right: 0;
         @include flex;
         &__button {
            @include flex;
            justify-content: center;
            overflow: hidden;
            align-items: center;
            &__wrapper {
               @include flex;
               align-items: center;
               justify-content: center;
               padding: 0 15px;
               &__text {
                  @include flex;
                  align-items: center;
                  color: #FFFFFF;
                  font-size: 15px;
                  text-align: center;
                  justify-content: center;
               }
            }
         }
      }
   }
</style>