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