next-swipe-action.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <view class="next-slide" :class="{'next-slide-disabled': disabled}">
  3. <view class="next-slide-left" :style="'position: relative;left:'+left+'rpx'" @touchstart="ontouchstart"
  4. @touchmove="ontouchmove" @touchend="ontouchend">
  5. <slot></slot>
  6. </view>
  7. <view class="next-slide-right">
  8. <view
  9. class="next-btn-item"
  10. v-for="(item,index) in btnGroup"
  11. :key="index"
  12. :style="getStyle(item)"
  13. @click.stop="btnClick(item)">
  14. {{item.name}}
  15. </view>
  16. </view>
  17. </view>
  18. </template>
  19. <script>
  20. const defBtnStyle = {
  21. width: '100rpx',
  22. bgColor: '#f9ae3d',
  23. color: '#FFFFFF',
  24. fontSize: '28rpx',
  25. fontWeight: 300
  26. };
  27. export default {
  28. name: 'NextSwipeAction',
  29. props: {
  30. btnGroup: {
  31. type: Array,
  32. default: () => {
  33. return [
  34. // {
  35. // name: '修改',
  36. // style: {
  37. // bgColor: '#f9ae3d'
  38. // }
  39. // },
  40. {
  41. name: '删除',
  42. style: {
  43. bgColor: '#ff4d4f'
  44. }
  45. }]
  46. }
  47. },
  48. //当前列索引
  49. index: {
  50. type: Number,
  51. require: true,
  52. default: 0
  53. },
  54. //是否禁用
  55. disabled: {
  56. type: Boolean,
  57. default: false
  58. },
  59. // 是否按钮点击后自定重置
  60. btnClickAutoReset: {
  61. type: Boolean,
  62. default: true
  63. }
  64. },
  65. data() {
  66. return {
  67. x: 0,
  68. left: 0,
  69. operation: 0,
  70. height: 0,
  71. screenWidth: 0
  72. };
  73. },
  74. mounted() {
  75. this.$nextTick(res => {
  76. const systemInfo = uni.getSystemInfoSync()
  77. this.screenWidth = systemInfo.screenWidth
  78. this.getBtnWidth()
  79. this.getListHeight()
  80. })
  81. },
  82. methods: {
  83. getStyle(item) {
  84. const style = item.style || {};
  85. const styleStr = 'width:'+ (style.width || defBtnStyle.width) +
  86. ';height:' + this.height +
  87. 'rpx;background-color:' + (style.bgColor || defBtnStyle.bgColor) +
  88. ';color:' + (style.color || defBtnStyle.color) +
  89. ';font-size:' + (style.fontSize || defBtnStyle.fontSize) +
  90. 'font-weight:' + (style.fontWeight || defBtnStyle.fontWeight);
  91. return styleStr
  92. },
  93. btnClick(item) {
  94. const it = Object.assign({}, item);
  95. delete it.style;
  96. this.$emit('btnClick', {
  97. index: this.index,
  98. item: it
  99. })
  100. if(this.btnClickAutoReset) {
  101. this.reset()
  102. }
  103. },
  104. //重置方法
  105. reset() {
  106. this.left = 0
  107. },
  108. getBtnWidth() {
  109. const element = uni.createSelectorQuery().in(this).select(".next-slide-right");
  110. element.boundingClientRect(rect => {
  111. this.operation = this.px2rpx(rect.width, this.screenWidth)
  112. }).exec()
  113. },
  114. getListHeight() {
  115. const element = uni.createSelectorQuery().in(this).select(".next-slide-left");
  116. element.boundingClientRect(rect => {
  117. this.height = this.px2rpx(rect.height, this.screenWidth)
  118. }).exec()
  119. },
  120. px2rpx(px, screenWidth) {
  121. return px / (screenWidth / 750)
  122. },
  123. ontouchstart(e) {
  124. if(this.disabled) return
  125. this.x = this.px2rpx(e.touches[0].clientX, this.screenWidth)
  126. },
  127. ontouchmove(e) {
  128. if(this.disabled) return
  129. let clientX = this.x - this.px2rpx(e.touches[0].clientX, this.screenWidth)
  130. if (clientX <= 0) this.left = 0
  131. else if (this.operation <= clientX) this.left = this.operation * -1
  132. else this.left = clientX * -1
  133. },
  134. ontouchend(e) {
  135. if(this.disabled) return
  136. let clientX = this.x - this.px2rpx(e.changedTouches[0].clientX, this.screenWidth)
  137. this.left = clientX > this.operation / 2 ? this.operation * -1 : 0
  138. },
  139. }
  140. }
  141. </script>
  142. <style scoped>
  143. .next-slide {
  144. width: 100%;
  145. position: relative;
  146. overflow: hidden;
  147. }
  148. .next-slide-disabled {
  149. background-color: #333333;
  150. opacity: 0.6;
  151. }
  152. .next-slide-left {
  153. width: 100%;
  154. overflow: hidden;
  155. background-color: #FFFFFF;
  156. transition: left 0.2s ease-in-out;
  157. z-index: 999;
  158. }
  159. .next-slide-right {
  160. position: absolute;
  161. top: 0rpx;
  162. right: 0;
  163. z-index: 99;
  164. display: flex;
  165. align-items: center;
  166. justify-content: flex-end;
  167. }
  168. .next-btn-item {
  169. display: flex;
  170. align-items: center;
  171. justify-content: center;
  172. }
  173. </style>