uni-swipe-action-item.vue 11 KB

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