u-swipe-action-item.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. <template>
  2. <!-- #ifdef MP-ALIPAY -->
  3. <!-- <import-sjs from="./alipay.sjs" name="mysjs" /> -->
  4. <!-- #endif -->
  5. <view class="u-swipe-action-item" ref="u-swipe-action-item">
  6. <view class="u-swipe-action-item__right">
  7. <slot name="button">
  8. <view v-for="(item,index) in options" :key="index" class="u-swipe-action-item__right__button"
  9. :ref="`u-swipe-action-item__right__button-${index}`" :style="[{
  10. alignItems: item.style && item.style.borderRadius ? 'center' : 'stretch'
  11. }]" @tap="buttonClickHandler(item, index)">
  12. <view class="u-swipe-action-item__right__button__wrapper" :style="[{
  13. backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
  14. borderRadius: item.style && item.style.borderRadius ? item.style.borderRadius : '0',
  15. padding: item.style && item.style.borderRadius ? '0' : '0 15px',
  16. }, item.style]">
  17. <u-icon v-if="item.icon" :name="item.icon"
  18. :color="item.style && item.style.color ? item.style.color : '#ffffff'"
  19. :size="item.iconSize ? addUnit(item.iconSize) : item.style && item.style.fontSize ? getPx(item.style.fontSize) * 1.2 : 17"
  20. :customStyle="{
  21. marginRight: item.text ? '2px' : 0
  22. }"></u-icon>
  23. <text v-if="item.text" class="u-swipe-action-item__right__button__wrapper__text u-line-1"
  24. :style="[{
  25. color: item.style && item.style.color ? item.style.color : '#ffffff',
  26. fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px',
  27. lineHeight: item.style && item.style.fontSize ? item.style.fontSize : '16px',
  28. }]">{{ item.text }}</text>
  29. </view>
  30. </view>
  31. </slot>
  32. </view>
  33. <!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
  34. <view class="u-swipe-action-item__content" @touchstart="wxs.touchstart" @touchmove="wxs.touchmove"
  35. @touchend="wxs.touchend" :status="status" :change:status="wxs.statusChange" :size="size"
  36. :change:size="wxs.sizeChange">
  37. <slot></slot>
  38. </view>
  39. <!-- #endif -->
  40. <!-- #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO-->
  41. <view class="u-swipe-action-item__content" @click="clickHandler" @touchstart="touchstart" @touchmove="touchmove"
  42. @touchend="touchend" :style="sliderStyle">
  43. <slot></slot>
  44. </view>
  45. <!-- <view class="u-swipe-action-item__content" @touchstart="mysjs.touchstart" @touchmove="mysjs.touchmove"
  46. @touchend="mysjs.touchend">
  47. <slot></slot>
  48. </view> -->
  49. <!-- #endif -->
  50. <!-- #ifdef APP-NVUE -->
  51. <view class="u-swipe-action-item__content" ref="u-swipe-action-item__content" @panstart="onTouchstart"
  52. @tap="clickHandler">
  53. <slot></slot>
  54. </view>
  55. <!-- #endif -->
  56. </view>
  57. </template>
  58. <!-- #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5 -->
  59. <script src="./index.wxs" module="wxs" lang="wxs"></script>
  60. <!-- #endif -->
  61. <script>
  62. import { touchMixin } from '../../libs/mixin/touch'
  63. import { props } from './props';
  64. import { mpMixin } from '../../libs/mixin/mpMixin';
  65. import { mixin } from '../../libs/mixin/mixin';
  66. import { addUnit, getPx, sleep } from '../../libs/function/index';
  67. // #ifdef APP-NVUE
  68. import nvue from './nvue.js';
  69. // #endif
  70. // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5
  71. import wxs from './wxs.js';
  72. // #endif
  73. // #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
  74. import other from './other.js';
  75. // #endif
  76. /**
  77. * SwipeActionItem 滑动单元格子组件
  78. * @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
  79. * @tutorial https://ijry.github.io/uview-plus/components/swipeAction.html
  80. * @property {Boolean} show 控制打开或者关闭(默认 false )
  81. * @property {String | Number} index 标识符,如果是v-for,可用index索引
  82. * @property {Boolean} disabled 是否禁用(默认 false )
  83. * @property {Boolean} autoClose 是否自动关闭其他swipe按钮组(默认 true )
  84. * @property {Number} threshold 滑动距离阈值,只有大于此值,才被认为是要打开菜单(默认 30 )
  85. * @property {Array} options 右侧按钮内容
  86. * @property {String | Number} duration 动画过渡时间,单位ms(默认 350 )
  87. * @event {Function(index)} open 组件打开时触发
  88. * @event {Function(index)} close 组件关闭时触发
  89. * @example <u-swipe-action><u-swipe-action-item :options="options1" ></u-swipe-action-item></u-swipe-action>
  90. */
  91. export default {
  92. name: 'u-swipe-action-item',
  93. emits: ['click', 'update:show'],
  94. mixins: [
  95. mpMixin,
  96. mixin,
  97. // #ifndef APP-NVUE
  98. touchMixin,
  99. // #endif
  100. // #ifdef APP-NVUE
  101. nvue,
  102. // #endif
  103. // #ifdef APP-VUE || MP-WEIXIN || MP-QQ || H5
  104. wxs,
  105. // #endif
  106. // #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO
  107. other,
  108. // #endif
  109. props
  110. ],
  111. data() {
  112. return {
  113. // 按钮的尺寸信息
  114. size: {},
  115. // 父组件u-swipe-action的参数
  116. parentData: {
  117. autoClose: true,
  118. },
  119. // 当前状态,open-打开,close-关闭
  120. status: '',
  121. sliderStyle: {}
  122. }
  123. },
  124. watch: {
  125. // 由于wxs无法直接读取外部的值,需要在外部值变化时,重新执行赋值逻辑
  126. // #ifndef APP-NVUE
  127. wxsInit(newValue, oldValue) {
  128. this.queryRect()
  129. },
  130. // #endif
  131. status(newValue) {
  132. if (newValue === 'open') {
  133. this.$emit('update:show', true)
  134. this.parent && this.parent.setOpendItem(this)
  135. } else {
  136. this.$emit('update:show', false)
  137. }
  138. },
  139. show(newValue) {
  140. if (newValue) {
  141. this.status = 'open'
  142. } else {
  143. this.status = 'close'
  144. }
  145. }
  146. },
  147. computed: {
  148. wxsInit() {
  149. return [this.disabled, this.autoClose, this.threshold, this.options, this.duration]
  150. }
  151. },
  152. mounted() {
  153. this.init()
  154. },
  155. beforeUmount() {
  156. this.closeHandler()
  157. },
  158. methods: {
  159. addUnit,
  160. getPx,
  161. init() {
  162. // 初始化父组件数据
  163. this.updateParentData()
  164. // #ifndef APP-NVUE
  165. sleep().then(() => {
  166. this.queryRect()
  167. })
  168. // #endif
  169. },
  170. updateParentData() {
  171. // 此方法在mixin中
  172. this.getParentData('u-swipe-action')
  173. },
  174. // #ifndef APP-NVUE
  175. // 查询节点
  176. queryRect() {
  177. this.$uGetRect('.u-swipe-action-item__right__button', true).then(buttons => {
  178. this.size = {
  179. buttons,
  180. show: this.show,
  181. disabled: this.disabled,
  182. threshold: this.threshold,
  183. duration: this.duration
  184. }
  185. })
  186. },
  187. // #endif
  188. // 按钮被点击
  189. buttonClickHandler(item, index) {
  190. let ret = this.$emit('click', {
  191. index,
  192. name: this.name
  193. }, () => {
  194. })
  195. if (this.closeOnClick) {
  196. this.closeHandler()
  197. }
  198. }
  199. },
  200. }
  201. </script>
  202. <style lang="scss" scoped>
  203. @import "../../libs/css/components.scss";
  204. .u-swipe-action-item {
  205. position: relative;
  206. overflow: hidden;
  207. /* #ifndef APP-NVUE || MP-WEIXIN */
  208. touch-action: pan-y;
  209. /* #endif */
  210. &__content {
  211. transform: translateX(0px); // 修复某些情况下默认右侧按钮是展开的问题
  212. background-color: #FFFFFF;
  213. z-index: 10;
  214. }
  215. &__right {
  216. position: absolute;
  217. top: 0;
  218. bottom: 0;
  219. right: 0;
  220. @include flex;
  221. &__button {
  222. @include flex;
  223. justify-content: center;
  224. overflow: hidden;
  225. align-items: center;
  226. &__wrapper {
  227. @include flex;
  228. align-items: center;
  229. justify-content: center;
  230. padding: 0 15px;
  231. &__text {
  232. @include flex;
  233. align-items: center;
  234. color: #FFFFFF;
  235. font-size: 15px;
  236. text-align: center;
  237. justify-content: center;
  238. }
  239. }
  240. }
  241. }
  242. }
  243. </style>