uni-popup.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. "use strict";
  2. const common_vendor = require("../../../../common/vendor.js");
  3. const _sfc_main = {
  4. name: "uniPopup",
  5. components: {},
  6. emits: ["change", "maskClick"],
  7. props: {
  8. // 开启动画
  9. animation: {
  10. type: Boolean,
  11. default: true
  12. },
  13. // 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
  14. // message: 消息提示 ; dialog : 对话框
  15. type: {
  16. type: String,
  17. default: "center"
  18. },
  19. // maskClick
  20. isMaskClick: {
  21. type: Boolean,
  22. default: null
  23. },
  24. // TODO 2 个版本后废弃属性 ,使用 isMaskClick
  25. maskClick: {
  26. type: Boolean,
  27. default: null
  28. },
  29. backgroundColor: {
  30. type: String,
  31. default: "none"
  32. },
  33. safeArea: {
  34. type: Boolean,
  35. default: true
  36. },
  37. maskBackgroundColor: {
  38. type: String,
  39. default: "rgba(0, 0, 0, 0.4)"
  40. }
  41. },
  42. watch: {
  43. /**
  44. * 监听type类型
  45. */
  46. type: {
  47. handler: function(type) {
  48. if (!this.config[type])
  49. return;
  50. this[this.config[type]](true);
  51. },
  52. immediate: true
  53. },
  54. isDesktop: {
  55. handler: function(newVal) {
  56. if (!this.config[newVal])
  57. return;
  58. this[this.config[this.type]](true);
  59. },
  60. immediate: true
  61. },
  62. /**
  63. * 监听遮罩是否可点击
  64. * @param {Object} val
  65. */
  66. maskClick: {
  67. handler: function(val) {
  68. this.mkclick = val;
  69. },
  70. immediate: true
  71. },
  72. isMaskClick: {
  73. handler: function(val) {
  74. this.mkclick = val;
  75. },
  76. immediate: true
  77. },
  78. // H5 下禁止底部滚动
  79. showPopup(show) {
  80. }
  81. },
  82. data() {
  83. return {
  84. duration: 300,
  85. ani: [],
  86. showPopup: false,
  87. showTrans: false,
  88. popupWidth: 0,
  89. popupHeight: 0,
  90. config: {
  91. top: "top",
  92. bottom: "bottom",
  93. center: "center",
  94. left: "left",
  95. right: "right",
  96. message: "top",
  97. dialog: "center",
  98. share: "bottom"
  99. },
  100. maskClass: {
  101. position: "fixed",
  102. bottom: 0,
  103. top: 0,
  104. left: 0,
  105. right: 0,
  106. backgroundColor: "rgba(0, 0, 0, 0.4)"
  107. },
  108. transClass: {
  109. position: "fixed",
  110. left: 0,
  111. right: 0
  112. },
  113. maskShow: true,
  114. mkclick: true,
  115. popupstyle: this.isDesktop ? "fixforpc-top" : "top"
  116. };
  117. },
  118. computed: {
  119. isDesktop() {
  120. return this.popupWidth >= 500 && this.popupHeight >= 500;
  121. },
  122. bg() {
  123. if (this.backgroundColor === "" || this.backgroundColor === "none") {
  124. return "transparent";
  125. }
  126. return this.backgroundColor;
  127. }
  128. },
  129. mounted() {
  130. const fixSize = () => {
  131. const {
  132. windowWidth,
  133. windowHeight,
  134. windowTop,
  135. safeArea,
  136. screenHeight,
  137. safeAreaInsets
  138. } = common_vendor.index.getSystemInfoSync();
  139. this.popupWidth = windowWidth;
  140. this.popupHeight = windowHeight + (windowTop || 0);
  141. if (safeArea && this.safeArea) {
  142. this.safeAreaInsets = screenHeight - safeArea.bottom;
  143. } else {
  144. this.safeAreaInsets = 0;
  145. }
  146. };
  147. fixSize();
  148. },
  149. // TODO vue3
  150. unmounted() {
  151. this.setH5Visible();
  152. },
  153. created() {
  154. if (this.isMaskClick === null && this.maskClick === null) {
  155. this.mkclick = true;
  156. } else {
  157. this.mkclick = this.isMaskClick !== null ? this.isMaskClick : this.maskClick;
  158. }
  159. if (this.animation) {
  160. this.duration = 300;
  161. } else {
  162. this.duration = 0;
  163. }
  164. this.messageChild = null;
  165. this.clearPropagation = false;
  166. this.maskClass.backgroundColor = this.maskBackgroundColor;
  167. },
  168. methods: {
  169. setH5Visible() {
  170. },
  171. /**
  172. * 公用方法,不显示遮罩层
  173. */
  174. closeMask() {
  175. this.maskShow = false;
  176. },
  177. /**
  178. * 公用方法,遮罩层禁止点击
  179. */
  180. disableMask() {
  181. this.mkclick = false;
  182. },
  183. // TODO nvue 取消冒泡
  184. clear(e) {
  185. e.stopPropagation();
  186. this.clearPropagation = true;
  187. },
  188. open(direction) {
  189. if (this.showPopup) {
  190. return;
  191. }
  192. let innerType = ["top", "center", "bottom", "left", "right", "message", "dialog", "share"];
  193. if (!(direction && innerType.indexOf(direction) !== -1)) {
  194. direction = this.type;
  195. }
  196. if (!this.config[direction]) {
  197. console.error("缺少类型:", direction);
  198. return;
  199. }
  200. this[this.config[direction]]();
  201. this.$emit("change", {
  202. show: true,
  203. type: direction
  204. });
  205. },
  206. close(type) {
  207. this.showTrans = false;
  208. this.$emit("change", {
  209. show: false,
  210. type: this.type
  211. });
  212. clearTimeout(this.timer);
  213. this.timer = setTimeout(() => {
  214. this.showPopup = false;
  215. }, 300);
  216. },
  217. // TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
  218. touchstart() {
  219. this.clearPropagation = false;
  220. },
  221. onTap() {
  222. if (this.clearPropagation) {
  223. this.clearPropagation = false;
  224. return;
  225. }
  226. this.$emit("maskClick");
  227. if (!this.mkclick)
  228. return;
  229. this.close();
  230. },
  231. /**
  232. * 顶部弹出样式处理
  233. */
  234. top(type) {
  235. this.popupstyle = this.isDesktop ? "fixforpc-top" : "top";
  236. this.ani = ["slide-top"];
  237. this.transClass = {
  238. position: "fixed",
  239. left: 0,
  240. right: 0,
  241. backgroundColor: this.bg
  242. };
  243. if (type)
  244. return;
  245. this.showPopup = true;
  246. this.showTrans = true;
  247. this.$nextTick(() => {
  248. if (this.messageChild && this.type === "message") {
  249. this.messageChild.timerClose();
  250. }
  251. });
  252. },
  253. /**
  254. * 底部弹出样式处理
  255. */
  256. bottom(type) {
  257. this.popupstyle = "bottom";
  258. this.ani = ["slide-bottom"];
  259. this.transClass = {
  260. position: "fixed",
  261. left: 0,
  262. right: 0,
  263. bottom: 0,
  264. paddingBottom: this.safeAreaInsets + "px",
  265. backgroundColor: this.bg
  266. };
  267. if (type)
  268. return;
  269. this.showPopup = true;
  270. this.showTrans = true;
  271. },
  272. /**
  273. * 中间弹出样式处理
  274. */
  275. center(type) {
  276. this.popupstyle = "center";
  277. this.ani = ["zoom-out", "fade"];
  278. this.transClass = {
  279. position: "fixed",
  280. display: "flex",
  281. flexDirection: "column",
  282. bottom: 0,
  283. left: 0,
  284. right: 0,
  285. top: 0,
  286. justifyContent: "center",
  287. alignItems: "center"
  288. };
  289. if (type)
  290. return;
  291. this.showPopup = true;
  292. this.showTrans = true;
  293. },
  294. left(type) {
  295. this.popupstyle = "left";
  296. this.ani = ["slide-left"];
  297. this.transClass = {
  298. position: "fixed",
  299. left: 0,
  300. bottom: 0,
  301. top: 0,
  302. backgroundColor: this.bg,
  303. display: "flex",
  304. flexDirection: "column"
  305. };
  306. if (type)
  307. return;
  308. this.showPopup = true;
  309. this.showTrans = true;
  310. },
  311. right(type) {
  312. this.popupstyle = "right";
  313. this.ani = ["slide-right"];
  314. this.transClass = {
  315. position: "fixed",
  316. bottom: 0,
  317. right: 0,
  318. top: 0,
  319. backgroundColor: this.bg,
  320. display: "flex",
  321. flexDirection: "column"
  322. };
  323. if (type)
  324. return;
  325. this.showPopup = true;
  326. this.showTrans = true;
  327. }
  328. }
  329. };
  330. if (!Array) {
  331. const _easycom_uni_transition2 = common_vendor.resolveComponent("uni-transition");
  332. _easycom_uni_transition2();
  333. }
  334. const _easycom_uni_transition = () => "../../../uni-transition/components/uni-transition/uni-transition.js";
  335. if (!Math) {
  336. _easycom_uni_transition();
  337. }
  338. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  339. return common_vendor.e({
  340. a: $data.showPopup
  341. }, $data.showPopup ? common_vendor.e({
  342. b: $data.maskShow
  343. }, $data.maskShow ? {
  344. c: common_vendor.o($options.onTap),
  345. d: common_vendor.p({
  346. name: "mask",
  347. ["mode-class"]: "fade",
  348. styles: $data.maskClass,
  349. duration: $data.duration,
  350. show: $data.showTrans
  351. })
  352. } : {}, {
  353. e: $options.bg,
  354. f: common_vendor.n($data.popupstyle),
  355. g: common_vendor.o((...args) => $options.clear && $options.clear(...args)),
  356. h: common_vendor.o($options.onTap),
  357. i: common_vendor.p({
  358. ["mode-class"]: $data.ani,
  359. name: "content",
  360. styles: $data.transClass,
  361. duration: $data.duration,
  362. show: $data.showTrans
  363. }),
  364. j: common_vendor.o((...args) => $options.touchstart && $options.touchstart(...args)),
  365. k: common_vendor.n($data.popupstyle),
  366. l: common_vendor.n($options.isDesktop ? "fixforpc-z-index" : "")
  367. }) : {});
  368. }
  369. const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "F:/development/HbuildWorkspace/KPS/uni_modules/uni-popup/components/uni-popup/uni-popup.vue"]]);
  370. wx.createComponent(Component);