vue列表左滑刪除組件

vue 列表左滑刪除組件

定義組件

list_drop.vue

<template>
  <div class="slider">
    <div class="content" @touchstart="touchStart" @touchmove="touchMove" @touchend="touchEnd" :style="deleteSlider">
      <!-- 插槽中放具體項目中需要內容 -->
      <slot name="img"></slot>
      <slot name="title"></slot>
      <slot name="price"></slot>
      <!-- 默認插槽 -->
      <slot></slot>
      <div class="remove" ref="remove" @click="deleteLine">
        <slot name="delete">
          <div class="remove-content">刪除</div>
        </slot>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: 'ListDrop',
  props: ['index'],
  data() {
    return {
      startX: 0, //觸摸位置
      endX: 0, //結束位置
      moveX: 0, //滑動時的位置
      disX: 0, //移動距離
      deleteSlider: '' //滑動時的效果,使用v-bind:style="deleteSlider"
    }
  },
  methods: {
    touchStart(ev) {
      ev = ev || event
      //tounches類數組,等於1時表示此時有隻有一隻手指在觸摸屏幕
      if (ev.touches.length == 1) {
        // 記錄開始位置
        this.startX = ev.touches[0].clientX
      }
    },
    touchMove(ev) {
      ev = ev || event
      //獲取刪除按鈕的寬度,此寬度爲滑塊左滑的最大距離
      let wd = this.$refs.remove.offsetWidth
      if (ev.touches.length == 1) {
        // 滑動時距離瀏覽器左側實時距離
        this.moveX = ev.touches[0].clientX
        //起始位置減去 實時的滑動的距離,得到手指實時偏移距離
        this.disX = this.startX - this.moveX
        //console.log(this.disX)
        // 如果是向右滑動或者不滑動,不改變滑塊的位置
        if (this.disX < 0 || this.disX == 0) {
          this.deleteSlider = 'transform:translateX(0px)'
        } else if (this.disX > 0) {
          // 大於0,表示左滑了,此時滑塊開始滑動
          //具體滑動距離我取的是 手指偏移距離*5。
          this.deleteSlider = 'transform:translateX(-' + this.disX * 5 + 'px)'
          // 最大也只能等於刪除按鈕寬度
          if (this.disX * 5 >= wd) {
            this.deleteSlider = 'transform:translateX(-' + wd + 'px)'
          }
        }
      }
    },
    touchEnd(ev) {
      ev = ev || event
      let wd = this.$refs.remove.offsetWidth
      if (ev.changedTouches.length == 1) {
        let endX = ev.changedTouches[0].clientX
        this.disX = this.startX - endX
        //console.log(this.disX)
        //如果距離小於刪除按鈕一半,強行回到起點
        if (this.disX * 5 < wd / 2) {
          this.deleteSlider = 'transform:translateX(0px)'
        } else {
          //大於一半 滑動到最大值
          this.deleteSlider = 'transform:translateX(-' + wd + 'px)'
        }
      }
    },
    deleteLine() {
      this.deleteSlider = 'transform:translateX(0px)'
      this.$emit('deleteLine')
    }
  }
}
</script>

<style lang="scss" scoped>
@import '~assets/scss/mixin';
.content {
  transition: all 0.2s ease-in-out 0s;
  @include flex(flex-start, row, center);
}

.slider {
  @include flex(flex-start, row, center);
  .remove {
    flex: 1;
    &-content {
      max-width: 42px;
      padding: 5px;
      white-space: nowrap;
      background-color: #e04d4d;
      color: #fff;
    }
  }
}
</style>

mixin.scss

@mixin flex($mainAxis:flex-start, $direction:row, $crossAxis:flex-start) {
  display: flex;
  flex-direction: $direction;
  justify-content: $mainAxis;
  align-items: $crossAxis;
}

@mixin no-wrap-multi($n:2) {
  display: -webkit-box;
  overflow: hidden;
  text-overflow: ellipsis;
  -webkit-line-clamp: $n;
  -webkit-box-orient: vertical;
  word-break: break-all;
}

使用

<template>
 	<list-drop
 		class="list"
        v-for="(item, index) in list"
        :key="index"
        @deleteLine="deleteCard(item.cardId)"
      >
      		<div class="item">
				{{item.name}}
			</div>
			<div slot="delete">
					<div class="item-delete">解綁</div>
			</div>
      </list-drop>
</template>

<script>
	import ListDrop from '@/components/list_drop.vue'
	export default {
		name: 'bankCard',
		components: {ListDrop},
		data: {
			return {
				list: [
					{id:1, name: 'item1'},
					{id:2, name: 'item2'},
				]
			}
		},
		mothods: {
			deleteCard(id) {
				this.list.forEach((item, index) => {
					if(item.id === id){
						this.list.splice(index, 1)
					}
				})
			}
		}
	}
</script>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章