swipe-action

swipe-action滑动菜单

组件结构

  1. <template>
  2. <viewclass="tui-swipeout-wrap">
  3. <viewclass="tui-swipeout-item" :class="[isShowBtn?'swipe-action-show':'']" @touchstart="handlerTouchstart"
  4. @touchmove="handlerTouchmove" @touchend="handlerTouchend" :style="{transform:'translate('+ position.pageX +'px,0);'}">
  5. <viewclass="tui-swipeout-content">
  6. <slotname="content"></slot>
  7. </view>
  8. <viewclass="tui-swipeout-button-right-group"v-if="actions.length > 0" @touchend.stop="loop">
  9. <viewclass="tui-swipeout-button-right-item"v-for="(item,index) in actions" :key="index" :style="{background:item.background ||'#f7f7f7',color:item.color,width:item.width+'px'}"
  10. :data-index="index" @tap="handlerButton">
  11. <image :src="item.icon"v-if="item.icon" :style="{width:px(item.imgWidth),height:px(item.imgHeight)}"></image>
  12. <text :style="{fontSize:px(item.fontsize)}">{{item.name}}</text>
  13. </view>
  14. </view>
  15. <!--actions长度设置为0,可直接传按钮进来-->
  16. <viewclass="tui-swipeout-button-right-group" @touchend.stop="loop" @tap="handlerParentButton"v-if="actions.length === 0"
  17. :style="{width:operateWidth+'px',right:'-'+operateWidth+'px'}">
  18. <slotname="button"></slot>
  19. </view>
  20. </view>
  21. <viewv-if="isShowBtn && showMask"class="swipe-action_mask" @tap="closeButtonGroup" @touchmove.stop="closeButtonGroup"/>
  22. </view>
  23. </template>

组件脚本

  1. <script>
  2. exportdefault{
  3. name:"tuiSwipeAction",
  4. props:{
  5. // name: '删除',
  6. // color: '#fff',
  7. // fontsize: 32,//单位upx
  8. // width: 80, //单位px
  9. // icon: 'like.png',//此处为图片地址
  10. // background: '#ed3f14'
  11. actions:{
  12. type:Array,
  13. default:[]
  14. },
  15. //是否可关闭,默认可关闭,可以单独控制
  16. closable:{
  17. type:Boolean,
  18. default:true
  19. },
  20. //设为false,可以滑动多行不关闭菜单
  21. showMask:{
  22. type:Boolean,
  23. default:true
  24. },
  25. operateWidth:{
  26. type:Number,
  27. default:80
  28. },
  29. params:{
  30. type:Object,
  31. default:{}
  32. }
  33. },
  34. watch:{
  35. actions(newValue, oldValue){
  36. this.updateButtonSize()
  37. }
  38. },
  39. data(){
  40. return{
  41. //start position
  42. tStart:{
  43. pageX:0,
  44. pageY:0
  45. },
  46. //限制滑动距离
  47. limitMove:0,
  48. //move position
  49. position:{
  50. pageX:0,
  51. pageY:0
  52. },
  53. isShowBtn:false
  54. };
  55. },
  56. // #ifdef H5
  57. mounted(){
  58. this.updateButtonSize()
  59. },
  60. // #endif
  61. onReady(){
  62. this.updateButtonSize()
  63. },
  64. methods:{
  65. swipeDirection(x1, x2, y1, y2){
  66. returnMath.abs(x1 - x2)>=
  67. Math.abs(y1 - y2)?(x1 - x2 >0?'Left':'Right'):(y1 - y2 >0?'Up':'Down')
  68. },
  69. //阻止事件冒泡
  70. loop(){},
  71. updateButtonSize(){
  72. const actions =this.actions;
  73. if(actions.length >0){
  74. const query = uni.createSelectorQuery().in(this);
  75. let limitMovePosition =0;
  76. actions.forEach(item =>{
  77. limitMovePosition += item.width ||0;
  78. });
  79. this.limitMove = limitMovePosition;
  80. }else{
  81. this.limitMove =this.operateWidth;
  82. }
  83. },
  84. handlerTouchstart(event){
  85. const touches = event.touches ? event.touches[0]:{};
  86. const tStart =this.tStart;
  87. if(touches){
  88. for(let i in tStart){
  89. if(touches[i]){
  90. tStart[i]= touches[i];
  91. }
  92. }
  93. }
  94. },
  95. swipper(touches){
  96. const start =this.tStart;
  97. const spacing ={
  98. pageX: touches.pageX - start.pageX,
  99. pageY: touches.pageY - start.pageY
  100. }
  101. if(this.limitMove <Math.abs(spacing.pageX)){
  102. spacing.pageX =-this.limitMove;
  103. }
  104. this.position = spacing
  105. },
  106. handlerTouchmove(event){
  107. const start =this.tStart;
  108. const touches = event.touches ? event.touches[0]:{};
  109. if(touches){
  110. const direction =this.swipeDirection(start.pageX, touches.pageX, start.pageY, touches.pageY);
  111. if(direction ==='Left'){
  112. this.swipper(touches);
  113. }
  114. }
  115. },
  116. handlerTouchend(event){
  117. const start =this.tStart;
  118. const touches = event.changedTouches ? event.changedTouches[0]:{};
  119. if(touches){
  120. const direction =this.swipeDirection(start.pageX, touches.pageX, start.pageY, touches.pageY);
  121. const spacing ={
  122. pageX: touches.pageX - start.pageX,
  123. pageY: touches.pageY - start.pageY
  124. }
  125. if(Math.abs(spacing.pageX)>=40&& direction ==="Left"){
  126. spacing.pageX = spacing.pageX <0?-this.limitMove :this.limitMove;
  127. this.isShowBtn =true
  128. }else{
  129. spacing.pageX =0;
  130. }
  131. this.position = spacing
  132. }
  133. },
  134. handlerButton(event){
  135. if(this.closable){
  136. this.closeButtonGroup();
  137. }
  138. const dataset = event.currentTarget.dataset;
  139. this.$emit('click',{
  140. index:Number(dataset.index),
  141. item:this.params
  142. })
  143. },
  144. closeButtonGroup(){
  145. this.position ={
  146. pageX:0,
  147. pageY:0
  148. };
  149. this.isShowBtn =false
  150. },
  151. //控制自定义组件
  152. handlerParentButton(event){
  153. if(this.closable){
  154. this.closeButtonGroup();
  155. }
  156. },
  157. px(num){
  158. return uni.upx2px(num)+"px"
  159. }
  160. }
  161. }
  162. </script>

组件样式

  1. ...此处省略n

脚本说明

  1. props:
  2. "actions":按钮信息,类型:"Array",默认值:[],数组内容:
  3. [
  4. name:'删除',
  5. color:'#fff',
  6. fontsize:32,//单位upx
  7. width:80,//单位px
  8. icon:'like.png',//此处为图片地址
  9. background:'#ed3f14'
  10. ]
  11. "closable":是否可关闭,默认可关闭,可以单独控制,类型:"Boolean",默认值:true
  12. "showMask":是否显示遮罩,设为false,可以滑动多行不关闭菜单,类型:"Boolean",默认值:true
  13. "operateWidth":按钮宽度,类型:"Number",默认值:80px
  14. "params":参数,类型:"Object",默认值:{}
  15. methods:
  16. "handlerButton":按钮点击事件
  17. "closeButtonGroup":关闭滑动

示例

  1. ...此处省略n行,下载源码查看