uview-pro 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/changelog.md +584 -574
  2. package/components/common/props.ts +22 -22
  3. package/components/u-action-sheet/types.ts +37 -37
  4. package/components/u-action-sheet/u-action-sheet.vue +178 -178
  5. package/components/u-alert-tips/types.ts +41 -41
  6. package/components/u-alert-tips/u-alert-tips.vue +238 -238
  7. package/components/u-avatar/types.ts +36 -36
  8. package/components/u-avatar/u-avatar.vue +217 -217
  9. package/components/u-avatar-cropper/types.ts +23 -23
  10. package/components/u-avatar-cropper/u-avatar-cropper.vue +297 -297
  11. package/components/u-avatar-cropper/weCropper.d.ts +62 -62
  12. package/components/u-avatar-cropper/weCropper.js +1281 -1281
  13. package/components/u-avatar-cropper/weCropper.ts +1276 -1276
  14. package/components/u-back-top/types.ts +36 -36
  15. package/components/u-back-top/u-back-top.vue +140 -140
  16. package/components/u-badge/types.ts +38 -38
  17. package/components/u-badge/u-badge.vue +183 -183
  18. package/components/u-button/types.ts +66 -66
  19. package/components/u-button/u-button.vue +579 -579
  20. package/components/u-calendar/types.ts +75 -75
  21. package/components/u-calendar/u-calendar.vue +793 -793
  22. package/components/u-car-keyboard/types.ts +14 -14
  23. package/components/u-car-keyboard/u-car-keyboard.vue +262 -262
  24. package/components/u-card/types.ts +61 -61
  25. package/components/u-card/u-card.vue +209 -209
  26. package/components/u-cell-group/types.ts +19 -19
  27. package/components/u-cell-group/u-cell-group.vue +60 -60
  28. package/components/u-cell-item/types.ts +56 -56
  29. package/components/u-cell-item/u-cell-item.vue +226 -226
  30. package/components/u-checkbox/types.ts +33 -33
  31. package/components/u-checkbox/u-checkbox.vue +282 -282
  32. package/components/u-checkbox-group/types.ts +34 -34
  33. package/components/u-checkbox-group/u-checkbox-group.vue +130 -130
  34. package/components/u-circle-progress/types.ts +54 -54
  35. package/components/u-circle-progress/u-circle-progress.vue +206 -206
  36. package/components/u-city-select/types.ts +22 -22
  37. package/components/u-city-select/u-city-select.vue +276 -276
  38. package/components/u-col/types.ts +32 -32
  39. package/components/u-col/u-col.vue +142 -142
  40. package/components/u-collapse/types.ts +33 -33
  41. package/components/u-collapse/u-collapse.vue +190 -190
  42. package/components/u-collapse-item/types.ts +27 -27
  43. package/components/u-collapse-item/u-collapse-item.vue +290 -290
  44. package/components/u-column-notice/types.ts +50 -50
  45. package/components/u-column-notice/u-column-notice.vue +222 -222
  46. package/components/u-count-down/types.ts +44 -44
  47. package/components/u-count-down/u-count-down.vue +286 -286
  48. package/components/u-count-to/types.ts +34 -34
  49. package/components/u-count-to/u-count-to.vue +266 -266
  50. package/components/u-divider/types.ts +33 -33
  51. package/components/u-divider/u-divider.vue +145 -145
  52. package/components/u-dropdown/types.ts +34 -34
  53. package/components/u-dropdown/u-dropdown.vue +330 -330
  54. package/components/u-dropdown-item/types.ts +29 -29
  55. package/components/u-dropdown-item/u-dropdown-item.vue +120 -120
  56. package/components/u-empty/types.ts +38 -38
  57. package/components/u-empty/u-empty.vue +103 -103
  58. package/components/u-field/types.ts +71 -71
  59. package/components/u-field/u-field.vue +388 -388
  60. package/components/u-form/types.ts +29 -29
  61. package/components/u-form/u-form.vue +130 -130
  62. package/components/u-form-item/types.ts +72 -72
  63. package/components/u-form-item/u-form-item.vue +447 -447
  64. package/components/u-full-screen/types.ts +16 -16
  65. package/components/u-full-screen/u-full-screen.vue +103 -103
  66. package/components/u-gap/types.ts +20 -20
  67. package/components/u-gap/u-gap.vue +50 -50
  68. package/components/u-grid/types.ts +21 -21
  69. package/components/u-grid/u-grid.vue +91 -91
  70. package/components/u-grid-item/types.ts +16 -16
  71. package/components/u-grid-item/u-grid-item.vue +130 -130
  72. package/components/u-icon/types.ts +61 -61
  73. package/components/u-icon/u-icon.vue +296 -296
  74. package/components/u-image/types.ts +51 -51
  75. package/components/u-image/u-image.vue +239 -239
  76. package/components/u-index-anchor/types.ts +16 -16
  77. package/components/u-index-anchor/u-index-anchor.vue +94 -94
  78. package/components/u-index-list/types.ts +43 -43
  79. package/components/u-index-list/u-index-list.vue +352 -352
  80. package/components/u-input/types.ts +137 -137
  81. package/components/u-input/u-input.vue +288 -288
  82. package/components/u-keyboard/types.ts +40 -40
  83. package/components/u-keyboard/u-keyboard.vue +178 -178
  84. package/components/u-lazy-load/types.ts +37 -37
  85. package/components/u-lazy-load/u-lazy-load.vue +246 -246
  86. package/components/u-line/types.ts +44 -44
  87. package/components/u-line/u-line.vue +68 -68
  88. package/components/u-line-progress/types.ts +58 -58
  89. package/components/u-line-progress/u-line-progress.vue +126 -126
  90. package/components/u-link/types.ts +43 -43
  91. package/components/u-link/u-link.vue +84 -84
  92. package/components/u-loading/types.ts +35 -35
  93. package/components/u-loading/u-loading.vue +105 -105
  94. package/components/u-loading-popup/types.ts +26 -26
  95. package/components/u-loading-popup/u-loading-popup.vue +253 -253
  96. package/components/u-loadmore/types.ts +79 -79
  97. package/components/u-loadmore/u-loadmore.vue +156 -156
  98. package/components/u-mask/types.ts +40 -40
  99. package/components/u-mask/u-mask.vue +113 -113
  100. package/components/u-message-input/types.ts +74 -74
  101. package/components/u-message-input/u-message-input.vue +281 -281
  102. package/components/u-modal/types.ts +118 -118
  103. package/components/u-modal/u-modal.vue +220 -220
  104. package/components/u-navbar/types.ts +103 -103
  105. package/components/u-navbar/u-navbar.vue +251 -251
  106. package/components/u-no-network/image.ts +2 -2
  107. package/components/u-no-network/types.ts +28 -28
  108. package/components/u-no-network/u-no-network.vue +303 -303
  109. package/components/u-notice-bar/types.ts +111 -111
  110. package/components/u-notice-bar/u-notice-bar.vue +189 -189
  111. package/components/u-number-box/types.ts +42 -42
  112. package/components/u-number-box/u-number-box.vue +321 -321
  113. package/components/u-number-keyboard/types.ts +26 -26
  114. package/components/u-number-keyboard/u-number-keyboard.vue +188 -188
  115. package/components/u-picker/types.ts +123 -123
  116. package/components/u-picker/u-picker.vue +685 -685
  117. package/components/u-popup/types.ts +59 -59
  118. package/components/u-popup/u-popup.vue +385 -385
  119. package/components/u-radio/types.ts +27 -27
  120. package/components/u-radio/u-radio.vue +279 -279
  121. package/components/u-radio-group/types.ts +31 -31
  122. package/components/u-radio-group/u-radio-group.vue +96 -96
  123. package/components/u-rate/types.ts +42 -42
  124. package/components/u-rate/u-rate.vue +249 -249
  125. package/components/u-read-more/types.ts +37 -37
  126. package/components/u-read-more/u-read-more.vue +172 -172
  127. package/components/u-root-portal/u-root-portal.vue +56 -56
  128. package/components/u-row/types.ts +22 -22
  129. package/components/u-row/u-row.vue +105 -105
  130. package/components/u-row-notice/types.ts +41 -41
  131. package/components/u-row-notice/u-row-notice.vue +256 -256
  132. package/components/u-safe-bottom/u-safe-bottom.vue +57 -57
  133. package/components/u-search/types.ts +55 -55
  134. package/components/u-search/u-search.vue +279 -279
  135. package/components/u-section/types.ts +34 -34
  136. package/components/u-section/u-section.vue +150 -150
  137. package/components/u-select/types.ts +45 -45
  138. package/components/u-select/u-select.vue +388 -388
  139. package/components/u-skeleton/types.ts +22 -22
  140. package/components/u-skeleton/u-skeleton.vue +231 -231
  141. package/components/u-slider/types.ts +34 -34
  142. package/components/u-slider/u-slider.vue +255 -255
  143. package/components/u-status-bar/u-status-bar.vue +74 -74
  144. package/components/u-steps/types.ts +30 -30
  145. package/components/u-steps/u-steps.vue +181 -181
  146. package/components/u-sticky/types.ts +24 -24
  147. package/components/u-sticky/u-sticky.vue +178 -178
  148. package/components/u-subsection/types.ts +38 -38
  149. package/components/u-subsection/u-subsection.vue +339 -339
  150. package/components/u-swipe-action/types.ts +52 -52
  151. package/components/u-swipe-action/u-swipe-action.vue +276 -276
  152. package/components/u-swiper/types.ts +49 -49
  153. package/components/u-swiper/u-swiper.vue +308 -308
  154. package/components/u-switch/types.ts +30 -30
  155. package/components/u-switch/u-switch.vue +150 -150
  156. package/components/u-tabbar/types.ts +38 -38
  157. package/components/u-tabbar/u-tabbar.vue +315 -315
  158. package/components/u-table/types.ts +27 -27
  159. package/components/u-table/u-table.vue +67 -67
  160. package/components/u-tabs/types.ts +53 -53
  161. package/components/u-tabs/u-tabs.vue +302 -302
  162. package/components/u-tabs-swiper/types.ts +55 -55
  163. package/components/u-tabs-swiper/u-tabs-swiper.vue +409 -409
  164. package/components/u-tag/types.ts +39 -39
  165. package/components/u-tag/u-tag.vue +268 -268
  166. package/components/u-td/types.ts +14 -14
  167. package/components/u-td/u-td.vue +98 -98
  168. package/components/u-text/types.ts +72 -72
  169. package/components/u-text/u-text.vue +343 -343
  170. package/components/u-th/types.ts +14 -14
  171. package/components/u-th/u-th.vue +92 -92
  172. package/components/u-time-line/u-time-line.vue +53 -53
  173. package/components/u-time-line-item/types.ts +16 -16
  174. package/components/u-time-line-item/u-time-line-item.vue +90 -90
  175. package/components/u-toast/types.ts +38 -38
  176. package/components/u-toast/u-toast.vue +240 -240
  177. package/components/u-top-tips/types.ts +16 -16
  178. package/components/u-top-tips/u-top-tips.vue +130 -130
  179. package/components/u-tr/types.ts +11 -11
  180. package/components/u-tr/u-tr.vue +39 -39
  181. package/components/u-upload/types.ts +82 -82
  182. package/components/u-upload/u-upload.vue +568 -568
  183. package/components/u-verification-code/types.ts +24 -24
  184. package/components/u-verification-code/u-verification-code.vue +176 -176
  185. package/components/u-waterfall/types.ts +18 -18
  186. package/components/u-waterfall/u-waterfall.vue +187 -187
  187. package/iconfont.css +913 -913
  188. package/index.scss +25 -25
  189. package/index.ts +38 -38
  190. package/libs/config/config.ts +26 -26
  191. package/libs/config/zIndex.ts +37 -37
  192. package/libs/css/color.scss +155 -155
  193. package/libs/css/common.scss +178 -178
  194. package/libs/css/style.components.scss +16 -16
  195. package/libs/css/style.h5.scss +8 -8
  196. package/libs/css/style.mp.scss +72 -72
  197. package/libs/css/style.nvue.scss +15 -15
  198. package/libs/css/style.vue.scss +188 -188
  199. package/libs/function/$parent.ts +24 -24
  200. package/libs/function/addUnit.ts +13 -13
  201. package/libs/function/color.ts +37 -37
  202. package/libs/function/colorGradient.ts +139 -139
  203. package/libs/function/debounce.ts +28 -28
  204. package/libs/function/deepClone.ts +39 -39
  205. package/libs/function/deepMerge.ts +35 -35
  206. package/libs/function/getParent.ts +63 -63
  207. package/libs/function/getRect.ts +26 -26
  208. package/libs/function/guid.ts +42 -42
  209. package/libs/function/md5.ts +403 -403
  210. package/libs/function/parent.ts +21 -21
  211. package/libs/function/queryParams.ts +64 -64
  212. package/libs/function/random.ts +16 -16
  213. package/libs/function/randomArray.ts +11 -11
  214. package/libs/function/route.ts +118 -118
  215. package/libs/function/styleUtils.ts +83 -83
  216. package/libs/function/sys.ts +15 -15
  217. package/libs/function/test.ts +289 -289
  218. package/libs/function/throttle.ts +31 -31
  219. package/libs/function/timeFormat.ts +55 -55
  220. package/libs/function/timeFrom.ts +48 -48
  221. package/libs/function/toast.ts +14 -14
  222. package/libs/function/trim.ts +21 -21
  223. package/libs/function/type2icon.ts +39 -39
  224. package/libs/hooks/index.ts +4 -4
  225. package/libs/hooks/useCompRelation.ts +364 -364
  226. package/libs/hooks/useComponent.ts +759 -759
  227. package/libs/hooks/useEmitter.ts +79 -79
  228. package/libs/hooks/useParent.ts +33 -33
  229. package/libs/hooks/useRect.ts +33 -33
  230. package/libs/index.ts +337 -337
  231. package/libs/request/auto-http.ts +76 -76
  232. package/libs/request/index.ts +242 -242
  233. package/libs/store/index.ts +88 -88
  234. package/libs/util/async-validator.d.ts +75 -75
  235. package/libs/util/async-validator.js +1 -1
  236. package/libs/util/calendar.d.ts +57 -57
  237. package/libs/util/emitter.ts +112 -112
  238. package/libs/util/eventBus.ts +86 -86
  239. package/libs/util/logger.ts +364 -364
  240. package/libs/util/mitt.ts +118 -118
  241. package/libs/util/parent.ts +20 -20
  242. package/package.json +4 -4
  243. package/readme.md +241 -241
  244. package/theme.scss +38 -38
  245. package/types/components.d.ts +97 -97
  246. package/types/global.d.ts +331 -331
  247. package/types/ignore-errors.d.ts +30 -30
  248. package/types/index.d.ts +19 -19
  249. package/types/uni-app.d.ts +63 -63
@@ -1,330 +1,330 @@
1
- <template>
2
- <view class="u-dropdown" :style="$u.toStyle(styles, customStyle)" :class="customClass">
3
- <view
4
- class="u-dropdown__menu"
5
- :style="{ height: $u.addUnit(height) }"
6
- :class="{ 'u-border-bottom': borderBottom }"
7
- >
8
- <view
9
- class="u-dropdown__menu__item"
10
- v-for="(item, index) in menuList"
11
- :key="index"
12
- @tap.stop="menuClick(index)"
13
- >
14
- <view class="u-flex">
15
- <text
16
- class="u-dropdown__menu__item__text"
17
- :style="{
18
- color: item.disabled
19
- ? '#c0c4cc'
20
- : index === current || highlightIndex == index
21
- ? activeColor
22
- : inactiveColor,
23
- fontSize: $u.addUnit(titleSize)
24
- }"
25
- >{{ item.title }}</text
26
- >
27
- <view
28
- class="u-dropdown__menu__item__arrow"
29
- :class="{
30
- 'u-dropdown__menu__item__arrow--rotate': index === current
31
- }"
32
- >
33
- <u-icon
34
- :custom-style="{ display: 'flex' }"
35
- :name="menuIcon"
36
- :size="$u.addUnit(menuIconSize)"
37
- :color="index === current || highlightIndex == index ? activeColor : '#c0c4cc'"
38
- ></u-icon>
39
- </view>
40
- </view>
41
- </view>
42
- </view>
43
- <view
44
- class="u-dropdown__content"
45
- :style="[
46
- contentStyle,
47
- {
48
- transition: `opacity ${Number(duration) / 1000}s linear`,
49
- top: $u.addUnit(height),
50
- height: contentHeight + 'px'
51
- }
52
- ]"
53
- @tap="maskClick"
54
- @touchmove.stop.prevent
55
- >
56
- <view @tap.stop.prevent class="u-dropdown__content__popup" :style="[popupStyle]">
57
- <slot></slot>
58
- </view>
59
- <view class="u-dropdown__content__mask"></view>
60
- </view>
61
- </view>
62
- </template>
63
-
64
- <script lang="ts">
65
- export default {
66
- name: 'u-dropdown',
67
- options: {
68
- addGlobalClass: true,
69
- // #ifndef MP-TOUTIAO
70
- virtualHost: true,
71
- // #endif
72
- styleIsolation: 'shared'
73
- }
74
- };
75
- </script>
76
-
77
- <script setup lang="ts">
78
- import { ref, computed, onMounted, getCurrentInstance, nextTick } from 'vue';
79
- import { $u, useParent } from '../..';
80
- import { DropdownProps } from './types';
81
-
82
- /**
83
- * dropdown 下拉菜单
84
- * @description 该组件一般用于向下展开菜单,同时可切换多个选项卡的场景
85
- * @tutorial https://uviewpro.cn/zh/components/dropdown.html
86
- * @property {String} active-color 标题和选项卡选中的颜色(默认#2979ff)
87
- * @property {String} inactive-color 标题和选项卡未选中的颜色(默认#606266)
88
- * @property {Boolean} close-on-click-mask 点击遮罩是否关闭菜单(默认true)
89
- * @property {Boolean} close-on-click-self 点击当前激活项标题是否关闭菜单(默认true)
90
- * @property {String | Number} duration 选项卡展开和收起的过渡时间,单位ms(默认300)
91
- * @property {String | Number} height 标题菜单的高度,单位任意(默认80)
92
- * @property {String | Number} border-radius 菜单展开内容下方的圆角值,单位任意(默认0)
93
- * @property {Boolean} border-bottom 标题菜单是否显示下边框(默认false)
94
- * @property {String | Number} title-size 标题的字体大小,单位任意,数值默认为rpx单位(默认28)
95
- * @event {Function} open 下拉菜单被打开时触发
96
- * @event {Function} close 下拉菜单被关闭时触发
97
- * @example <u-dropdown></u-dropdown>
98
- */
99
-
100
- const props = defineProps(DropdownProps);
101
- const emit = defineEmits(['open', 'close']);
102
-
103
- const { children } = useParent('u-dropdown');
104
- // 菜单列表
105
- const menuList = ref<any[]>([]);
106
- // 下拉菜单的状态
107
- const active = ref(false);
108
- // 当前激活菜单索引
109
- // 当前是第几个菜单处于激活状态,小程序中此处不能写成false或者"",否则后续将current赋值为0,
110
- // 无能的TX没有使用===而是使用==判断,导致程序认为前后二者没有变化,从而不会触发视图更新
111
- const current = ref<number>(99999);
112
- // 外层内容样式
113
- const contentStyle = ref<any>({ zIndex: -1, opacity: 0 });
114
- // 高亮菜单索引
115
- const highlightIndex = ref<number>(99999);
116
- // 下拉内容高度
117
- const contentHeight = ref<number>(0);
118
- // 子组件引用
119
- const instance = getCurrentInstance();
120
- // 兼容头条样式
121
- const styles = computed(() => {
122
- const style: any = {};
123
- // #ifdef MP-TOUTIAO
124
- style.width = '100vw';
125
- // #endif
126
- return style;
127
- });
128
-
129
- // 下拉出来部分的样式
130
- const popupStyle = computed<any>(() => {
131
- const style: any = {};
132
- // 进行Y轴位移,展开状态时,恢复原位。收齐状态时,往上位移100%,进行隐藏
133
- style.transform = `translateY(${active.value ? 0 : '-100%'})`;
134
- style['transition-duration'] = Number(props.duration) / 1000 + 's';
135
- style.borderRadius = `0 0 ${$u.addUnit(props.borderRadius)} ${$u.addUnit(props.borderRadius)}`;
136
- return style;
137
- });
138
-
139
- // 生命周期
140
- onMounted(() => {
141
- getContentHeight();
142
- });
143
-
144
- /**
145
- * 初始化所有子组件
146
- * 当某个子组件内容变化时,触发父组件的init,父组件再让每一个子组件重新初始化一遍
147
- * 以保证数据的正确性
148
- */
149
- function init() {
150
- menuList.value = [];
151
- children.forEach(child => {
152
- menuList.value.push({
153
- title: child?.getExposed()?.props.title ?? '',
154
- disabled: child?.getExposed()?.props.disabled ?? false
155
- });
156
- });
157
- }
158
-
159
- /**
160
- * 点击菜单
161
- * @param index 菜单索引
162
- */
163
- function menuClick(index: number) {
164
- // 判断是否被禁用
165
- if (menuList.value[index]?.disabled) return;
166
- // 如果点击时的索引和当前激活项索引相同,意味着点击了激活项,需要收起下拉菜单
167
- if (index === current.value && props.closeOnClickSelf) {
168
- close();
169
- // 等动画结束后,再移除下拉菜单中的内容,否则直接移除,也就没有下拉菜单收起的效果了
170
- setTimeout(() => {
171
- if (children[index]) children[index]?.getExposed()?.setActive(false);
172
- }, Number(props.duration));
173
- return;
174
- }
175
- open(index);
176
- }
177
-
178
- /**
179
- * 打开下拉菜单
180
- * @param index 菜单索引
181
- */
182
- function open(index: number) {
183
- // 嵌套popup使用时可能获取不到正确的高度,重新计算
184
- if (contentHeight.value < 1) getContentHeight();
185
- // 重置高亮索引,否则会造成多个菜单同时高亮
186
- // highlightIndex.value = 9999;
187
- // 展开时,设置下拉内容的样式
188
- contentStyle.value = { zIndex: 11 };
189
- // 标记展开状态以及当前展开项的索引
190
- active.value = true;
191
- current.value = index;
192
- // 历遍所有的子元素,将索引匹配的项标记为激活状态,因为子元素是通过v-if控制切换的
193
- // 之所以不是因display: none,是因为nvue没有display这个属性
194
- children.forEach((child, idx) => {
195
- child?.getExposed()?.setActive(index == idx ? true : false);
196
- });
197
- emit('open', current.value);
198
- }
199
-
200
- /**
201
- * 设置下拉菜单处于收起状态
202
- */
203
- function close() {
204
- emit('close', current.value);
205
- // 设置为收起状态,同时current归位,设置为空字符串
206
- active.value = false;
207
- current.value = 99999;
208
- // 下拉内容的样式进行调整,不透明度设置为0
209
- contentStyle.value = { zIndex: -1, opacity: 0 };
210
- }
211
-
212
- /**
213
- * 点击遮罩
214
- */
215
- function maskClick() {
216
- // 如果不允许点击遮罩,直接返回
217
- if (!props.closeOnClickMask) return;
218
- close();
219
- }
220
-
221
- /**
222
- * 外部手动设置某个菜单高亮
223
- * @param index 菜单索引
224
- */
225
- function highlight(index?: number) {
226
- highlightIndex.value = index !== undefined ? index : 99999;
227
- }
228
-
229
- /**
230
- * 获取下拉菜单内容的高度
231
- * 这里的原理为,因为dropdown组件是相对定位的,它的下拉出来的内容,必须给定一个高度
232
- * 才能让遮罩占满菜单一下,直到屏幕底部的高度
233
- * this.$u.sys()为uView封装的获取设备信息的方法
234
- */
235
- function getContentHeight() {
236
- const windowHeight = $u.sys().windowHeight;
237
-
238
- $u.getRect('.u-dropdown__menu', instance).then((res: any) => {
239
- // 这里获取的是dropdown的尺寸,在H5上,uniapp获取尺寸是有bug的(以前提出修复过,后来又出现了此bug,目前hx2.8.11版本)
240
- // H5端bug表现为元素尺寸的top值为导航栏底部到到元素的上边沿的距离,但是元素的bottom值确是导航栏顶部到元素底部的距离
241
- // 二者是互相矛盾的,本质原因是H5端导航栏非原生,uni的开发者大意造成
242
- // 这里取菜单栏的botton值合理的,不能用res.top,否则页面会造成滚动
243
- contentHeight.value = windowHeight - res.bottom;
244
- });
245
- }
246
-
247
- onMounted(() => {
248
- nextTick(() => {
249
- init();
250
- });
251
- });
252
-
253
- // 暴露方法
254
- defineExpose({
255
- init,
256
- close,
257
- open,
258
- highlight,
259
- getContentHeight,
260
- children,
261
- menuList
262
- });
263
- </script>
264
-
265
- <style scoped lang="scss">
266
- @import '../../libs/css/style.components.scss';
267
-
268
- .u-dropdown {
269
- flex: 1;
270
- width: 100%;
271
- position: relative;
272
-
273
- &__menu {
274
- @include vue-flex;
275
- position: relative;
276
- z-index: 11;
277
- height: 80rpx;
278
-
279
- &__item {
280
- flex: 1;
281
- @include vue-flex;
282
- justify-content: center;
283
- align-items: center;
284
-
285
- &__text {
286
- font-size: 28rpx;
287
- color: $u-content-color;
288
- }
289
-
290
- &__arrow {
291
- margin-left: 6rpx;
292
- transition: transform 0.3s;
293
- align-items: center;
294
- @include vue-flex;
295
-
296
- &--rotate {
297
- transform: rotate(180deg);
298
- }
299
- }
300
- }
301
- }
302
-
303
- &__content {
304
- position: absolute;
305
- z-index: 8;
306
- width: 100%;
307
- left: 0px;
308
- bottom: 0;
309
- overflow: hidden;
310
-
311
- &__mask {
312
- position: absolute;
313
- z-index: 9;
314
- background: rgba(0, 0, 0, 0.3);
315
- width: 100%;
316
- left: 0;
317
- top: 0;
318
- bottom: 0;
319
- }
320
-
321
- &__popup {
322
- position: relative;
323
- z-index: 10;
324
- transition: all 0.3s;
325
- transform: translate3D(0, -100%, 0);
326
- overflow: hidden;
327
- }
328
- }
329
- }
330
- </style>
1
+ <template>
2
+ <view class="u-dropdown" :style="$u.toStyle(styles, customStyle)" :class="customClass">
3
+ <view
4
+ class="u-dropdown__menu"
5
+ :style="{ height: $u.addUnit(height) }"
6
+ :class="{ 'u-border-bottom': borderBottom }"
7
+ >
8
+ <view
9
+ class="u-dropdown__menu__item"
10
+ v-for="(item, index) in menuList"
11
+ :key="index"
12
+ @tap.stop="menuClick(index)"
13
+ >
14
+ <view class="u-flex">
15
+ <text
16
+ class="u-dropdown__menu__item__text"
17
+ :style="{
18
+ color: item.disabled
19
+ ? '#c0c4cc'
20
+ : index === current || highlightIndex == index
21
+ ? activeColor
22
+ : inactiveColor,
23
+ fontSize: $u.addUnit(titleSize)
24
+ }"
25
+ >{{ item.title }}</text
26
+ >
27
+ <view
28
+ class="u-dropdown__menu__item__arrow"
29
+ :class="{
30
+ 'u-dropdown__menu__item__arrow--rotate': index === current
31
+ }"
32
+ >
33
+ <u-icon
34
+ :custom-style="{ display: 'flex' }"
35
+ :name="menuIcon"
36
+ :size="$u.addUnit(menuIconSize)"
37
+ :color="index === current || highlightIndex == index ? activeColor : '#c0c4cc'"
38
+ ></u-icon>
39
+ </view>
40
+ </view>
41
+ </view>
42
+ </view>
43
+ <view
44
+ class="u-dropdown__content"
45
+ :style="[
46
+ contentStyle,
47
+ {
48
+ transition: `opacity ${Number(duration) / 1000}s linear`,
49
+ top: $u.addUnit(height),
50
+ height: contentHeight + 'px'
51
+ }
52
+ ]"
53
+ @tap="maskClick"
54
+ @touchmove.stop.prevent
55
+ >
56
+ <view @tap.stop.prevent class="u-dropdown__content__popup" :style="[popupStyle]">
57
+ <slot></slot>
58
+ </view>
59
+ <view class="u-dropdown__content__mask"></view>
60
+ </view>
61
+ </view>
62
+ </template>
63
+
64
+ <script lang="ts">
65
+ export default {
66
+ name: 'u-dropdown',
67
+ options: {
68
+ addGlobalClass: true,
69
+ // #ifndef MP-TOUTIAO
70
+ virtualHost: true,
71
+ // #endif
72
+ styleIsolation: 'shared'
73
+ }
74
+ };
75
+ </script>
76
+
77
+ <script setup lang="ts">
78
+ import { ref, computed, onMounted, getCurrentInstance, nextTick } from 'vue';
79
+ import { $u, useParent } from '../..';
80
+ import { DropdownProps } from './types';
81
+
82
+ /**
83
+ * dropdown 下拉菜单
84
+ * @description 该组件一般用于向下展开菜单,同时可切换多个选项卡的场景
85
+ * @tutorial https://uviewpro.cn/zh/components/dropdown.html
86
+ * @property {String} active-color 标题和选项卡选中的颜色(默认#2979ff)
87
+ * @property {String} inactive-color 标题和选项卡未选中的颜色(默认#606266)
88
+ * @property {Boolean} close-on-click-mask 点击遮罩是否关闭菜单(默认true)
89
+ * @property {Boolean} close-on-click-self 点击当前激活项标题是否关闭菜单(默认true)
90
+ * @property {String | Number} duration 选项卡展开和收起的过渡时间,单位ms(默认300)
91
+ * @property {String | Number} height 标题菜单的高度,单位任意(默认80)
92
+ * @property {String | Number} border-radius 菜单展开内容下方的圆角值,单位任意(默认0)
93
+ * @property {Boolean} border-bottom 标题菜单是否显示下边框(默认false)
94
+ * @property {String | Number} title-size 标题的字体大小,单位任意,数值默认为rpx单位(默认28)
95
+ * @event {Function} open 下拉菜单被打开时触发
96
+ * @event {Function} close 下拉菜单被关闭时触发
97
+ * @example <u-dropdown></u-dropdown>
98
+ */
99
+
100
+ const props = defineProps(DropdownProps);
101
+ const emit = defineEmits(['open', 'close']);
102
+
103
+ const { children } = useParent('u-dropdown');
104
+ // 菜单列表
105
+ const menuList = ref<any[]>([]);
106
+ // 下拉菜单的状态
107
+ const active = ref(false);
108
+ // 当前激活菜单索引
109
+ // 当前是第几个菜单处于激活状态,小程序中此处不能写成false或者"",否则后续将current赋值为0,
110
+ // 无能的TX没有使用===而是使用==判断,导致程序认为前后二者没有变化,从而不会触发视图更新
111
+ const current = ref<number>(99999);
112
+ // 外层内容样式
113
+ const contentStyle = ref<any>({ zIndex: -1, opacity: 0 });
114
+ // 高亮菜单索引
115
+ const highlightIndex = ref<number>(99999);
116
+ // 下拉内容高度
117
+ const contentHeight = ref<number>(0);
118
+ // 子组件引用
119
+ const instance = getCurrentInstance();
120
+ // 兼容头条样式
121
+ const styles = computed(() => {
122
+ const style: any = {};
123
+ // #ifdef MP-TOUTIAO
124
+ style.width = '100vw';
125
+ // #endif
126
+ return style;
127
+ });
128
+
129
+ // 下拉出来部分的样式
130
+ const popupStyle = computed<any>(() => {
131
+ const style: any = {};
132
+ // 进行Y轴位移,展开状态时,恢复原位。收齐状态时,往上位移100%,进行隐藏
133
+ style.transform = `translateY(${active.value ? 0 : '-100%'})`;
134
+ style['transition-duration'] = Number(props.duration) / 1000 + 's';
135
+ style.borderRadius = `0 0 ${$u.addUnit(props.borderRadius)} ${$u.addUnit(props.borderRadius)}`;
136
+ return style;
137
+ });
138
+
139
+ // 生命周期
140
+ onMounted(() => {
141
+ getContentHeight();
142
+ });
143
+
144
+ /**
145
+ * 初始化所有子组件
146
+ * 当某个子组件内容变化时,触发父组件的init,父组件再让每一个子组件重新初始化一遍
147
+ * 以保证数据的正确性
148
+ */
149
+ function init() {
150
+ menuList.value = [];
151
+ children.forEach(child => {
152
+ menuList.value.push({
153
+ title: child?.getExposed()?.props.title ?? '',
154
+ disabled: child?.getExposed()?.props.disabled ?? false
155
+ });
156
+ });
157
+ }
158
+
159
+ /**
160
+ * 点击菜单
161
+ * @param index 菜单索引
162
+ */
163
+ function menuClick(index: number) {
164
+ // 判断是否被禁用
165
+ if (menuList.value[index]?.disabled) return;
166
+ // 如果点击时的索引和当前激活项索引相同,意味着点击了激活项,需要收起下拉菜单
167
+ if (index === current.value && props.closeOnClickSelf) {
168
+ close();
169
+ // 等动画结束后,再移除下拉菜单中的内容,否则直接移除,也就没有下拉菜单收起的效果了
170
+ setTimeout(() => {
171
+ if (children[index]) children[index]?.getExposed()?.setActive(false);
172
+ }, Number(props.duration));
173
+ return;
174
+ }
175
+ open(index);
176
+ }
177
+
178
+ /**
179
+ * 打开下拉菜单
180
+ * @param index 菜单索引
181
+ */
182
+ function open(index: number) {
183
+ // 嵌套popup使用时可能获取不到正确的高度,重新计算
184
+ if (contentHeight.value < 1) getContentHeight();
185
+ // 重置高亮索引,否则会造成多个菜单同时高亮
186
+ // highlightIndex.value = 9999;
187
+ // 展开时,设置下拉内容的样式
188
+ contentStyle.value = { zIndex: 11 };
189
+ // 标记展开状态以及当前展开项的索引
190
+ active.value = true;
191
+ current.value = index;
192
+ // 历遍所有的子元素,将索引匹配的项标记为激活状态,因为子元素是通过v-if控制切换的
193
+ // 之所以不是因display: none,是因为nvue没有display这个属性
194
+ children.forEach((child, idx) => {
195
+ child?.getExposed()?.setActive(index == idx ? true : false);
196
+ });
197
+ emit('open', current.value);
198
+ }
199
+
200
+ /**
201
+ * 设置下拉菜单处于收起状态
202
+ */
203
+ function close() {
204
+ emit('close', current.value);
205
+ // 设置为收起状态,同时current归位,设置为空字符串
206
+ active.value = false;
207
+ current.value = 99999;
208
+ // 下拉内容的样式进行调整,不透明度设置为0
209
+ contentStyle.value = { zIndex: -1, opacity: 0 };
210
+ }
211
+
212
+ /**
213
+ * 点击遮罩
214
+ */
215
+ function maskClick() {
216
+ // 如果不允许点击遮罩,直接返回
217
+ if (!props.closeOnClickMask) return;
218
+ close();
219
+ }
220
+
221
+ /**
222
+ * 外部手动设置某个菜单高亮
223
+ * @param index 菜单索引
224
+ */
225
+ function highlight(index?: number) {
226
+ highlightIndex.value = index !== undefined ? index : 99999;
227
+ }
228
+
229
+ /**
230
+ * 获取下拉菜单内容的高度
231
+ * 这里的原理为,因为dropdown组件是相对定位的,它的下拉出来的内容,必须给定一个高度
232
+ * 才能让遮罩占满菜单一下,直到屏幕底部的高度
233
+ * this.$u.sys()为uView封装的获取设备信息的方法
234
+ */
235
+ function getContentHeight() {
236
+ const windowHeight = $u.sys().windowHeight;
237
+
238
+ $u.getRect('.u-dropdown__menu', instance).then((res: any) => {
239
+ // 这里获取的是dropdown的尺寸,在H5上,uniapp获取尺寸是有bug的(以前提出修复过,后来又出现了此bug,目前hx2.8.11版本)
240
+ // H5端bug表现为元素尺寸的top值为导航栏底部到到元素的上边沿的距离,但是元素的bottom值确是导航栏顶部到元素底部的距离
241
+ // 二者是互相矛盾的,本质原因是H5端导航栏非原生,uni的开发者大意造成
242
+ // 这里取菜单栏的botton值合理的,不能用res.top,否则页面会造成滚动
243
+ contentHeight.value = windowHeight - res.bottom;
244
+ });
245
+ }
246
+
247
+ onMounted(() => {
248
+ nextTick(() => {
249
+ init();
250
+ });
251
+ });
252
+
253
+ // 暴露方法
254
+ defineExpose({
255
+ init,
256
+ close,
257
+ open,
258
+ highlight,
259
+ getContentHeight,
260
+ children,
261
+ menuList
262
+ });
263
+ </script>
264
+
265
+ <style scoped lang="scss">
266
+ @import '../../libs/css/style.components.scss';
267
+
268
+ .u-dropdown {
269
+ flex: 1;
270
+ width: 100%;
271
+ position: relative;
272
+
273
+ &__menu {
274
+ @include vue-flex;
275
+ position: relative;
276
+ z-index: 11;
277
+ height: 80rpx;
278
+
279
+ &__item {
280
+ flex: 1;
281
+ @include vue-flex;
282
+ justify-content: center;
283
+ align-items: center;
284
+
285
+ &__text {
286
+ font-size: 28rpx;
287
+ color: $u-content-color;
288
+ }
289
+
290
+ &__arrow {
291
+ margin-left: 6rpx;
292
+ transition: transform 0.3s;
293
+ align-items: center;
294
+ @include vue-flex;
295
+
296
+ &--rotate {
297
+ transform: rotate(180deg);
298
+ }
299
+ }
300
+ }
301
+ }
302
+
303
+ &__content {
304
+ position: absolute;
305
+ z-index: 8;
306
+ width: 100%;
307
+ left: 0px;
308
+ bottom: 0;
309
+ overflow: hidden;
310
+
311
+ &__mask {
312
+ position: absolute;
313
+ z-index: 9;
314
+ background: rgba(0, 0, 0, 0.3);
315
+ width: 100%;
316
+ left: 0;
317
+ top: 0;
318
+ bottom: 0;
319
+ }
320
+
321
+ &__popup {
322
+ position: relative;
323
+ z-index: 10;
324
+ transition: all 0.3s;
325
+ transform: translate3D(0, -100%, 0);
326
+ overflow: hidden;
327
+ }
328
+ }
329
+ }
330
+ </style>