VUE左滑删除组件

西梁 2020年04月22日 284次浏览

效果图
直接上代码:

// 组件名:SlideDelete
<template>
  <div class="slide-delete">
    <div
      class="content"
      :style="{transform: `translateX(${ctnTransformX}px)`}"
      @touchstart="touchStart"
      @touchmove="touchMove"
      @touchend="touchEnd">
      <slot></slot>
    </div>
    <div
      @click.stop="remove"
      class="delete"
      ref="delBtn"
      :style="{transform: `translateX(${delBtnTransformX}px)`}">
      删除
    </div>
  </div>
</template>
<script>
export default {
  props: {
    id: {
      type: Number // 给组件绑定id,实现一个滑动时,另一个恢复
    },
    activeId: {
      type: Number // 当前滑动的组件id
    }
  },
  watch: {
    activeId () {
      if (this.id !== this.activeId) {
	// 恢复其他组件滑动状态
        this.ctnTransformX = 0
        this.delBtnTransformX = this.delBtnWidth
      }
    }
  },
  data () {
    return {
      startX: null,
      delBtnWidth: null,
      slideDistance: null,
      ctnTransformX: null,
      delBtnTransformX: null
    }
  },
  mounted () {
    this.delBtnWidth = this.$refs.delBtn.offsetWidth
    this.delBtnTransformX = this.delBtnWidth
  },
  methods: {
    remove () {
      this.$emit('remove') // 删除事件
    },
    touchStart (evt) {
      this.startX = evt.changedTouches[0].pageX
    },
    touchMove (evt) {
      this.slideDistance = this.startX - evt.changedTouches[0].pageX
      this.ctnTransformX = `-${this.slideDistance}`
      this.delBtnTransformX = this.delBtnWidth - this.slideDistance
      if (this.ctnTransformX < 0) {
        if (this.slideDistance > this.delBtnWidth) {
          this.ctnTransformX = `-${this.delBtnWidth}`
          this.delBtnTransformX = 0
        }
      } else {
        this.ctnTransformX = 0
        this.delBtnTransformX = this.delBtnWidth
      }
    },
    touchEnd () {
      if (this.slideDistance > this.delBtnWidth * 0.6) {
	// 滑动小于宽度的60%自动恢复,大于60%则完全展开
        this.ctnTransformX = `-${this.delBtnWidth}`
        this.delBtnTransformX = 0
      } else {
        this.ctnTransformX = 0
        this.delBtnTransformX = this.delBtnWidth
      }
      this.$emit('touchStart', this.id)
    }
  }
}
</script>
<style scoped lang="less">
.slide-delete {
  margin-top: 30px;
  position: relative;
  overflow: hidden;
  .content {
    transition: transform 260ms ease;
  }
  .delete {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 170px;
    height: 100%;
    position: absolute;
    right: 0;
    top: 0;
    font-size: 24px;
    color: #fff;
    background-color: #ff4400;
    transform: translateX(170px);
    transition: transform 260ms ease;
  }
}
</style>
// 使用组件
<slide-delete v-for="item in list"
:key="item.id"
@remove="remove(item.id)"
:id="item.id"
:activeId="activeId"
@touchStart="changeId">
  <div class="item">
     这里写组件内样式
  </div>
</slide-delete>
import SlideDelete from '@/components/SlideDelete'
components: {
  SlideDelete,
  Empty
},
data () {
  return {
    list: [], // 数据列表
    activeId: 0
  }
}