uni-popup-top.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <template>
  2. <view v-if="showPopup" class="uni-popup" :style="'top:'+top" @touchmove.stop.prevent="clear">
  3. <uni-transition :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans" @click="onTap" />
  4. <uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
  5. <view class="uni-popup__wrapper-box" @click.stop="clear">
  6. <slot />
  7. </view>
  8. </uni-transition>
  9. </view>
  10. </template>
  11. <script>
  12. import uniTransition from '../uni-transition/uni-transition-a.vue'
  13. /**
  14. * PopUp 弹出层
  15. * @description 弹出层组件,为了解决遮罩弹层的问题
  16. * @tutorial https://ext.dcloud.net.cn/plugin?id=329
  17. * @property {String} type = [top|center|bottom] 弹出方式
  18. * @value top 顶部弹出
  19. * @value center 中间弹出
  20. * @value bottom 底部弹出
  21. * @property {Boolean} animation = [ture|false] 是否开启动画
  22. * @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
  23. * @event {Function} change 打开关闭弹窗触发,e={show: false}
  24. */
  25. export default {
  26. name: 'UniPopup',
  27. components: {
  28. uniTransition
  29. },
  30. props: {
  31. // 开启动画
  32. animation: {
  33. type: Boolean,
  34. default: true
  35. },
  36. // 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
  37. type: {
  38. type: String,
  39. default: 'center'
  40. },
  41. // maskClick
  42. maskClick: {
  43. type: Boolean,
  44. default: true
  45. },
  46. top:String,
  47. position:String,
  48. maskClass:Object
  49. },
  50. data() {
  51. return {
  52. duration: 300,
  53. ani: [],
  54. showPopup: false,
  55. showTrans: false,
  56. // maskClass: {
  57. // 'position': 'fixed',
  58. // 'bottom': 0,
  59. // 'top': "226rpx",
  60. // 'left': 0,
  61. // 'right': 0,
  62. // 'backgroundColor': 'rgba(0, 0, 0, 0.4)'
  63. // },
  64. transClass: {
  65. 'position': 'fixed',
  66. 'left': 0,
  67. 'right': 0,
  68. }
  69. }
  70. },
  71. watch: {
  72. type: {
  73. handler: function(newVal) {
  74. switch (this.type) {
  75. case 'top':
  76. this.ani = ['slide-top']
  77. this.transClass = {
  78. 'position': 'fixed',
  79. 'left': 0,
  80. 'right': 0,
  81. }
  82. break
  83. case 'bottom':
  84. this.ani = ['slide-bottom']
  85. this.transClass = {
  86. 'position': 'fixed',
  87. 'left': 0,
  88. 'right': 0,
  89. 'bottom': 0
  90. }
  91. break
  92. case 'center':
  93. this.ani = ['zoom-out', 'fade']
  94. this.transClass = {
  95. 'position': 'fixed',
  96. /* #ifndef APP-NVUE */
  97. 'display': 'flex',
  98. 'flexDirection': 'column',
  99. /* #endif */
  100. 'bottom': 0,
  101. 'left': 0,
  102. 'right': 0,
  103. 'top': 0,
  104. 'justifyContent': 'center',
  105. 'alignItems': 'center'
  106. }
  107. break
  108. }
  109. },
  110. immediate: true
  111. }
  112. },
  113. created() {
  114. if (this.animation) {
  115. this.duration = 300
  116. } else {
  117. this.duration = 0
  118. }
  119. },
  120. methods: {
  121. clear(e) {
  122. // TODO nvue 取消冒泡
  123. e.stopPropagation()
  124. },
  125. open() {
  126. this.showPopup = true
  127. this.$nextTick(() => {
  128. clearTimeout(this.timer)
  129. this.timer = setTimeout(() => {
  130. this.showTrans = true
  131. }, 50);
  132. })
  133. this.$emit('change', {
  134. show: true
  135. })
  136. },
  137. close(type) {
  138. this.showTrans = false
  139. this.$nextTick(() => {
  140. clearTimeout(this.timer)
  141. this.timer = setTimeout(() => {
  142. this.$emit('change', {
  143. show: false
  144. })
  145. this.showPopup = false
  146. }, 300)
  147. })
  148. },
  149. onTap() {
  150. if (!this.maskClick) return
  151. this.close()
  152. }
  153. }
  154. }
  155. </script>
  156. <style scoped>
  157. .uni-popup {
  158. position: fixed;
  159. /* #ifdef H5 */
  160. /* top: var(--window-top); */
  161. /* #endif */
  162. /* #ifndef H5 */
  163. /* top: 0; */
  164. /* #endif */
  165. top: 226rpx;
  166. bottom: 0;
  167. left: 0;
  168. right: 0;
  169. z-index: 100;
  170. /* #ifndef APP-NVUE */
  171. /* #endif */
  172. }
  173. .uni-popup__mask {
  174. position: absolute;
  175. top: 0;
  176. bottom: 0;
  177. left: 0;
  178. right: 0;
  179. background-color: rgba(0, 0, 0, 0.4);
  180. opacity: 0;
  181. }
  182. .mask-ani {
  183. transition-property: opacity;
  184. transition-duration: 0.2s;
  185. }
  186. .uni-top-mask {
  187. opacity: 1;
  188. }
  189. .uni-bottom-mask {
  190. opacity: 1;
  191. }
  192. .uni-center-mask {
  193. opacity: 1;
  194. }
  195. .uni-popup__wrapper {
  196. /* #ifndef APP-NVUE */
  197. display: block;
  198. /* #endif */
  199. position: absolute;
  200. }
  201. .top {
  202. top: 0;
  203. left: 0;
  204. right: 0;
  205. transform: translateY(-500px);
  206. }
  207. .bottom {
  208. bottom: 0;
  209. left: 0;
  210. right: 0;
  211. transform: translateY(500px);
  212. }
  213. .center {
  214. /* #ifndef APP-NVUE */
  215. display: flex;
  216. flex-direction: column;
  217. /* #endif */
  218. bottom: 0;
  219. left: 0;
  220. right: 0;
  221. top: 0;
  222. justify-content: center;
  223. align-items: center;
  224. transform: scale(1.2);
  225. opacity: 0;
  226. }
  227. .uni-popup__wrapper-box {
  228. /* #ifndef APP-NVUE */
  229. display: block;
  230. /* #endif */
  231. position: relative;
  232. }
  233. .content-ani {
  234. /* transition: transform 0.3s;
  235. */
  236. transition-property: transform, opacity;
  237. transition-duration: 0.2s;
  238. }
  239. .uni-top-content {
  240. transform: translateY(0);
  241. }
  242. .uni-bottom-content {
  243. transform: translateY(0);
  244. }
  245. .uni-center-content {
  246. transform: scale(1);
  247. opacity: 1;
  248. }
  249. </style>