next-swipe-action.vue 4.0 KB

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