leftslip.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. <template>
  2. <div class="nut-leftslip">
  3. <div class="nut-leftslip-item" ref="slipItem" :class="{'leftslip-open':isOpen}">
  4. <div class="nut-leftslip-item-main" @touchstart="touchStart($event)" @touchmove="touchMove($event)"
  5. @touchend="touchEnd($event)">
  6. <slot name="slip-main"></slot>
  7. </div>
  8. <div class="nut-leftslip-item-btn" ref="right">
  9. <slot name="slipbtns">
  10. <!-- <a class="nut-delet-btn" @click.prevent="onlyDelClick($event)" v-if="onlyDelBtn">删除</a> -->
  11. </slot>
  12. </div>
  13. </div>
  14. </div>
  15. </template>
  16. <script>
  17. export default {
  18. name: 'nut-leftslip',
  19. props: {
  20. isMainSlide: {
  21. type: Boolean,
  22. default: true
  23. },
  24. isClickBack: {
  25. type: Boolean,
  26. default: true
  27. },
  28. // rightWidth: {
  29. // type: [Number, String],
  30. // default: 30
  31. // }
  32. },
  33. data() {
  34. return {
  35. startX: 0,
  36. startY: 0,
  37. moveX: 0,
  38. moveY: 0,
  39. buttonWidth: 0,
  40. pageWidth: null,
  41. startPos: 0,
  42. startLeft: 0,
  43. startRightW: 0,
  44. isOpen: false,
  45. };
  46. },
  47. mounted() {
  48. this.$nextTick(() => {
  49. if (this.onlyDelBtn) {
  50. return;
  51. }
  52. for (var slot of this.$slots.slipbtns) {
  53. this.buttonWidth = this.buttonWidth + slot.elm.offsetWidth;
  54. }
  55. });
  56. this.pageWidth = document.documentElement.clientWidth
  57. this.sliderEle = this.isMainSlide ? this.$refs.slipItem : this.$refs.right
  58. document.addEventListener('touchstart', this.handleRestet, false);
  59. // window.addEventListener('scroll', this.handleRestet, true);
  60. },
  61. beforeDestroy() {
  62. // 移除监听
  63. window.removeEventListener('touchstart', this.handleRestet, true);
  64. },
  65. methods: {
  66. handleRestet() {
  67. var slip = document.getElementsByClassName('leftslip-open');
  68. if (slip) {
  69. this.restSlide();
  70. }
  71. },
  72. onlyDelClick() {
  73. //一键删除模式点击删除
  74. this.$emit('oneDelete', this.$refs.slipItem);
  75. this.restSlide();
  76. },
  77. touchStart(e) {
  78. let parentElement = e.currentTarget.parentElement;
  79. if (e.touches.length == 1) {
  80. this.startX = e.touches[0].pageX;
  81. this.startY = e.touches[0].pageY;
  82. }
  83. const transform = this.sliderEle.style.transform
  84. this.startLeft = Number(transform ? transform.split('(')[1].split('px')[0] : 0)
  85. this.startRightW = this.startLeft < 0 ? Number(this.$refs.right.style.width.split('px')[0]) : 0;
  86. // console.log('startoleft2', this.sliderEle.style.transform, this.startLeft, this.startRightW)
  87. },
  88. touchMove(e) {
  89. let parentElement = e.currentTarget.parentElement;
  90. let disX = e.touches[0].pageX - this.startX // >0 右滑,<0 左滑
  91. if (e.touches.length == 1) {
  92. if (disX > 0 || (disX > 0 && this.startLeft >= 0) || (disX < 0 && disX > this.buttonWidth / 2)) { //禁止右滑
  93. return false
  94. } else {
  95. this.doSlide((-this.buttonWidth), true) // 最大滑动距离为右侧宽度
  96. }
  97. }
  98. },
  99. touchEnd(e) {
  100. // console.log('end')
  101. let parentElement = e.currentTarget.parentElement;
  102. const disX = e.changedTouches[0].pageX - this.startX // >0 右滑,<0 左滑
  103. let distance
  104. if (!this.isClickBack && disX === 0) { // 点击时不收起右侧
  105. return false
  106. }
  107. if ((-disX) > 50) { // 向左滑动超过阙值时,右侧滑出固定距离
  108. distance = this.buttonWidth > this.pageWidth ? this.pageWidth * 0.8 : this.buttonWidth;
  109. parentElement.className = 'nut-leftslip-item leftslip-open'
  110. parentElement.dataset.type = 1;
  111. } else { // 向左滑动未超过阙值,或向右滑动时,回原位
  112. distance = 0
  113. parentElement.className = 'nut-leftslip-item'
  114. parentElement.dataset.type = 0;
  115. }
  116. this.doSlide(-distance, true)
  117. // console.log('touchEnd', distance);
  118. },
  119. doSlide(distance, animate = false) {
  120. this.sliderEle.style.transform = `translateX(${distance}px)`
  121. this.$refs.right.style.width = -distance + 'px'
  122. if (this.isMainSlide) {
  123. this.sliderEle.style.transition = animate ? 'transform .5s' : 'initial'
  124. this.$refs.right.style.transition = animate ? 'width .5s' : 'initial'
  125. } else {
  126. this.sliderEle.style.transition = animate ? 'transform .5s, width .5s' : 'initial'
  127. }
  128. },
  129. restSlide() {
  130. let listItems = document.querySelectorAll('.nut-leftslip-item.leftslip-open');
  131. // 复位
  132. for (let i = 0; i < listItems.length; i++) {
  133. listItems[i].style = 'transform:translateX(0' + 'px)';
  134. listItems[i].dataset.type = 0; //是否展开标志位默认0,左滑展开为1,右滑隐藏为0
  135. this.isOpen = false;
  136. }
  137. }
  138. }
  139. };
  140. </script>