uni-swipe-action-item.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <template>
  2. <!-- 在微信小程序 app vue端 h5 使用wxs 实现-->
  3. <!-- #ifdef APP-VUE || MP-WEIXIN || H5 -->
  4. <view class="uni-swipe">
  5. <!-- #ifdef MP-WEIXIN || VUE3 -->
  6. <view class="uni-swipe_box" :change:prop="wxsswipe.showWatch" :prop="is_show" :data-threshold="threshold"
  7. :data-disabled="disabled" @touchstart="wxsswipe.touchstart" @touchmove="wxsswipe.touchmove"
  8. @touchend="wxsswipe.touchend">
  9. <!-- #endif -->
  10. <!-- #ifndef MP-WEIXIN || VUE3 -->
  11. <view class="uni-swipe_box" :change:prop="renderswipe.showWatch" :prop="is_show" :data-threshold="threshold"
  12. :data-disabled="disabled+''" @touchstart="renderswipe.touchstart" @touchmove="renderswipe.touchmove"
  13. @touchend="renderswipe.touchend">
  14. <!-- #endif -->
  15. <!-- 在微信小程序 app vue端 h5 使用wxs 实现-->
  16. <view class="uni-swipe_button-group button-group--left">
  17. <slot name="left">
  18. <view v-for="(item,index) in leftOptions" :key="index" :style="{
  19. backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
  20. }" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
  21. @touchend="appTouchEnd($event,index,item,'left')"
  22. @click.stop="onClickForPC(index,item,'left')">
  23. <text class="uni-swipe_button-text"
  24. :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
  25. </view>
  26. </slot>
  27. </view>
  28. <view class="uni-swipe_text--center">
  29. <slot></slot>
  30. </view>
  31. <view class="uni-swipe_button-group button-group--right">
  32. <slot name="right">
  33. <view v-for="(item,index) in rightOptions" :key="index" :style="{
  34. backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
  35. }" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
  36. @touchend="appTouchEnd($event,index,item,'right')"
  37. @click.stop="onClickForPC(index,item,'right')"><text class="uni-swipe_button-text"
  38. :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
  39. </view>
  40. </slot>
  41. </view>
  42. </view>
  43. </view>
  44. <!-- #endif -->
  45. <!-- app nvue端 使用 bindingx -->
  46. <!-- #ifdef APP-NVUE -->
  47. <view ref="selector-box--hock" class="uni-swipe" @horizontalpan="touchstart" @touchend="touchend">
  48. <view ref='selector-left-button--hock' class="uni-swipe_button-group button-group--left">
  49. <slot name="left">
  50. <view v-for="(item,index) in leftOptions" :key="index" :style="{
  51. backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
  52. }" class="uni-swipe_button button-hock" @click.stop="onClick(index,item,'left')"><text
  53. class="uni-swipe_button-text"
  54. :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF', fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
  55. </view>
  56. </slot>
  57. </view>
  58. <view ref='selector-right-button--hock' class="uni-swipe_button-group button-group--right">
  59. <slot name="right">
  60. <view v-for="(item,index) in rightOptions" :key="index" :style="{
  61. backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
  62. }" class="uni-swipe_button button-hock" @click.stop="onClick(index,item,'right')"><text
  63. class="uni-swipe_button-text"
  64. :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'}">{{ item.text }}</text>
  65. </view>
  66. </slot>
  67. </view>
  68. <view ref='selector-content--hock' class="uni-swipe_box">
  69. <slot></slot>
  70. </view>
  71. </view>
  72. <!-- #endif -->
  73. <!-- 其他平台使用 js ,长列表性能可能会有影响-->
  74. <!-- #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ -->
  75. <view class="uni-swipe">
  76. <view class="uni-swipe_box" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"
  77. :style="{transform:moveLeft}" :class="{ani:ani}">
  78. <view class="uni-swipe_button-group button-group--left" :class="[elClass]">
  79. <slot name="left">
  80. <view v-for="(item,index) in leftOptions" :key="index" :style="{
  81. backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
  82. fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
  83. }" class="uni-swipe_button button-hock" @touchstart="appTouchStart"
  84. @touchend="appTouchEnd($event,index,item,'left')"><text class="uni-swipe_button-text"
  85. :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}">{{ item.text }}</text>
  86. </view>
  87. </slot>
  88. </view>
  89. <slot></slot>
  90. <view class="uni-swipe_button-group button-group--right" :class="[elClass]">
  91. <slot name="right">
  92. <view v-for="(item,index) in rightOptions" :key="index" :style="{
  93. backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
  94. fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
  95. }" @touchstart="appTouchStart" @touchend="appTouchEnd($event,index,item,'right')"
  96. class="uni-swipe_button button-hock"><text class="uni-swipe_button-text"
  97. :style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}">{{ item.text }}</text>
  98. </view>
  99. </slot>
  100. </view>
  101. </view>
  102. </view>
  103. <!-- #endif -->
  104. </template>
  105. <script src="./wx.wxs" module="wxsswipe" lang="wxs"></script>
  106. <script module="renderswipe" lang="renderjs">
  107. import render from './render.js'
  108. export default {
  109. mounted(e, ins, owner) {
  110. this.state = {}
  111. },
  112. methods: {
  113. showWatch(newVal, oldVal, ownerInstance, instance) {
  114. render.showWatch(newVal, oldVal, ownerInstance, instance, this)
  115. },
  116. touchstart(e, ownerInstance) {
  117. render.touchstart(e, ownerInstance, this)
  118. },
  119. touchmove(e, ownerInstance) {
  120. render.touchmove(e, ownerInstance, this)
  121. },
  122. touchend(e, ownerInstance) {
  123. render.touchend(e, ownerInstance, this)
  124. }
  125. }
  126. }
  127. </script>
  128. <script>
  129. import mpwxs from './mpwxs'
  130. import bindingx from './bindingx.js'
  131. import mpother from './mpother'
  132. /**
  133. * SwipeActionItem 滑动操作子组件
  134. * @description 通过滑动触发选项的容器
  135. * @tutorial https://ext.dcloud.net.cn/plugin?id=181
  136. * @property {Boolean} show = [left|right|none] 开启关闭组件,auto-close = false 时生效
  137. * @property {Boolean} disabled = [true|false] 是否禁止滑动
  138. * @property {Boolean} autoClose = [true|false] 滑动打开当前组件,是否关闭其他组件
  139. * @property {Number} threshold 滑动缺省值
  140. * @property {Array} leftOptions 左侧选项内容及样式
  141. * @property {Array} rgihtOptions 右侧选项内容及样式
  142. * @event {Function} click 点击选项按钮时触发事件,e = {content,index} ,content(点击内容)、index(下标)
  143. * @event {Function} change 组件打开或关闭时触发,left\right\none
  144. */
  145. export default {
  146. mixins: [mpwxs, bindingx, mpother],
  147. emits: ['click', 'change'],
  148. props: {
  149. // 控制开关
  150. show: {
  151. type: String,
  152. default: 'none'
  153. },
  154. // 禁用
  155. disabled: {
  156. type: Boolean,
  157. default: false
  158. },
  159. // 是否自动关闭
  160. autoClose: {
  161. type: Boolean,
  162. default: true
  163. },
  164. // 滑动缺省距离
  165. threshold: {
  166. type: Number,
  167. default: 20
  168. },
  169. // 左侧按钮内容
  170. leftOptions: {
  171. type: Array,
  172. default () {
  173. return []
  174. }
  175. },
  176. // 右侧按钮内容
  177. rightOptions: {
  178. type: Array,
  179. default () {
  180. return []
  181. }
  182. }
  183. },
  184. // #ifndef VUE3
  185. // TODO vue2
  186. destroyed() {
  187. if (this.__isUnmounted) return
  188. this.uninstall()
  189. },
  190. // #endif
  191. // #ifdef VUE3
  192. // TODO vue3
  193. unmounted() {
  194. this.__isUnmounted = true
  195. this.uninstall()
  196. },
  197. // #endif
  198. methods: {
  199. uninstall() {
  200. if (this.swipeaction) {
  201. this.swipeaction.children.forEach((item, index) => {
  202. if (item === this) {
  203. this.swipeaction.children.splice(index, 1)
  204. }
  205. })
  206. }
  207. },
  208. /**
  209. * 获取父元素实例
  210. */
  211. getSwipeAction(name = 'uniSwipeAction') {
  212. let parent = this.$parent;
  213. let parentName = parent.$options.name;
  214. while (parentName !== name) {
  215. parent = parent.$parent;
  216. if (!parent) return false;
  217. parentName = parent.$options.name;
  218. }
  219. return parent;
  220. }
  221. }
  222. }
  223. </script>
  224. <style lang="scss">
  225. .uni-swipe {
  226. position: relative;
  227. /* #ifndef APP-NVUE */
  228. overflow: hidden;
  229. /* #endif */
  230. }
  231. .uni-swipe_box {
  232. /* #ifndef APP-NVUE */
  233. display: flex;
  234. flex-shrink: 0;
  235. // touch-action: none;
  236. /* #endif */
  237. position: relative;
  238. }
  239. .uni-swipe_content {
  240. // border: 1px red solid;
  241. }
  242. .uni-swipe_text--center {
  243. width: 100%;
  244. /* #ifndef APP-NVUE */
  245. cursor: grab;
  246. /* #endif */
  247. }
  248. .uni-swipe_button-group {
  249. /* #ifndef APP-NVUE */
  250. box-sizing: border-box;
  251. display: flex;
  252. /* #endif */
  253. flex-direction: row;
  254. position: absolute;
  255. top: 0;
  256. bottom: 0;
  257. /* #ifdef H5 */
  258. cursor: pointer;
  259. /* #endif */
  260. }
  261. .button-group--left {
  262. left: 0;
  263. transform: translateX(-100%)
  264. }
  265. .button-group--right {
  266. right: 0;
  267. transform: translateX(100%)
  268. }
  269. .uni-swipe_button {
  270. /* #ifdef APP-NVUE */
  271. flex: 1;
  272. /* #endif */
  273. /* #ifndef APP-NVUE */
  274. display: flex;
  275. /* #endif */
  276. flex-direction: row;
  277. justify-content: center;
  278. align-items: center;
  279. padding: 0 20px;
  280. }
  281. .uni-swipe_button-text {
  282. /* #ifndef APP-NVUE */
  283. flex-shrink: 0;
  284. /* #endif */
  285. font-size: 14px;
  286. }
  287. .ani {
  288. transition-property: transform;
  289. transition-duration: 0.3s;
  290. transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
  291. }
  292. /* #ifdef MP-ALIPAY */
  293. .movable-area {
  294. /* width: 100%; */
  295. height: 45px;
  296. }
  297. .movable-view {
  298. display: flex;
  299. /* justify-content: center; */
  300. position: relative;
  301. flex: 1;
  302. height: 45px;
  303. z-index: 2;
  304. }
  305. .movable-view-button {
  306. display: flex;
  307. flex-shrink: 0;
  308. flex-direction: row;
  309. height: 100%;
  310. background: #C0C0C0;
  311. }
  312. /* .transition {
  313. transition: all 0.3s;
  314. } */
  315. .movable-view-box {
  316. flex-shrink: 0;
  317. height: 100%;
  318. background-color: #fff;
  319. }
  320. /* #endif */
  321. </style>