uni-swipe-action-item.vue 10 KB

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