uview-pro 0.6.18 → 0.6.19

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 (278) hide show
  1. package/changelog.md +1778 -1768
  2. package/components/u-action-sheet/types.ts +52 -52
  3. package/components/u-action-sheet/u-action-sheet.vue +196 -196
  4. package/components/u-action-sheet-item/types.ts +35 -35
  5. package/components/u-action-sheet-item/u-action-sheet-item.vue +85 -85
  6. package/components/u-alert-tips/types.ts +49 -49
  7. package/components/u-alert-tips/u-alert-tips.vue +239 -239
  8. package/components/u-avatar/types.ts +44 -44
  9. package/components/u-avatar/u-avatar.vue +218 -218
  10. package/components/u-avatar-cropper/types.ts +23 -23
  11. package/components/u-avatar-cropper/u-avatar-cropper.vue +299 -299
  12. package/components/u-avatar-cropper/weCropper.d.ts +62 -62
  13. package/components/u-avatar-cropper/weCropper.js +1281 -1281
  14. package/components/u-avatar-cropper/weCropper.ts +1276 -1276
  15. package/components/u-back-top/types.ts +44 -44
  16. package/components/u-back-top/u-back-top.vue +141 -141
  17. package/components/u-badge/types.ts +46 -46
  18. package/components/u-badge/u-badge.vue +153 -153
  19. package/components/u-button/types.ts +76 -76
  20. package/components/u-button/u-button.vue +608 -608
  21. package/components/u-calendar/types.ts +126 -126
  22. package/components/u-calendar/u-calendar.vue +1243 -1243
  23. package/components/u-car-keyboard/types.ts +22 -22
  24. package/components/u-car-keyboard/u-car-keyboard.vue +263 -263
  25. package/components/u-card/types.ts +69 -69
  26. package/components/u-card/u-card.vue +210 -210
  27. package/components/u-cell-group/types.ts +27 -27
  28. package/components/u-cell-group/u-cell-group.vue +60 -60
  29. package/components/u-cell-item/types.ts +64 -64
  30. package/components/u-cell-item/u-cell-item.vue +221 -221
  31. package/components/u-checkbox/types.ts +45 -45
  32. package/components/u-checkbox/u-checkbox.vue +363 -363
  33. package/components/u-checkbox-group/types.ts +45 -45
  34. package/components/u-checkbox-group/u-checkbox-group.vue +172 -172
  35. package/components/u-circle-progress/types.ts +63 -63
  36. package/components/u-circle-progress/u-circle-progress.vue +299 -299
  37. package/components/u-city-select/types.ts +30 -30
  38. package/components/u-city-select/u-city-select.vue +281 -281
  39. package/components/u-col/types.ts +40 -40
  40. package/components/u-col/u-col.vue +142 -142
  41. package/components/u-collapse/types.ts +41 -41
  42. package/components/u-collapse/u-collapse.vue +190 -190
  43. package/components/u-collapse-item/types.ts +35 -35
  44. package/components/u-collapse-item/u-collapse-item.vue +291 -291
  45. package/components/u-column-notice/types.ts +58 -58
  46. package/components/u-column-notice/u-column-notice.vue +223 -223
  47. package/components/u-config-provider/types.ts +53 -53
  48. package/components/u-config-provider/u-config-provider.vue +185 -185
  49. package/components/u-count-down/types.ts +52 -52
  50. package/components/u-count-down/u-count-down.vue +288 -288
  51. package/components/u-count-to/types.ts +42 -42
  52. package/components/u-count-to/u-count-to.vue +266 -266
  53. package/components/u-divider/types.ts +41 -41
  54. package/components/u-divider/u-divider.vue +146 -146
  55. package/components/u-dropdown/types.ts +67 -67
  56. package/components/u-dropdown/u-dropdown.vue +436 -436
  57. package/components/u-dropdown-item/types.ts +40 -40
  58. package/components/u-dropdown-item/u-dropdown-item.vue +124 -124
  59. package/components/u-empty/types.ts +46 -46
  60. package/components/u-empty/u-empty.vue +109 -109
  61. package/components/u-fab/types.ts +83 -83
  62. package/components/u-fab/u-fab.vue +330 -330
  63. package/components/u-field/types.ts +81 -81
  64. package/components/u-field/u-field.vue +398 -398
  65. package/components/u-form/types.ts +39 -39
  66. package/components/u-form/u-form.vue +175 -135
  67. package/components/u-form-item/types.ts +95 -95
  68. package/components/u-form-item/u-form-item.vue +563 -563
  69. package/components/u-full-screen/types.ts +26 -26
  70. package/components/u-full-screen/u-full-screen.vue +100 -100
  71. package/components/u-gap/types.ts +28 -28
  72. package/components/u-gap/u-gap.vue +50 -50
  73. package/components/u-grid/types.ts +29 -29
  74. package/components/u-grid/u-grid.vue +91 -91
  75. package/components/u-grid-item/types.ts +24 -24
  76. package/components/u-grid-item/u-grid-item.vue +130 -130
  77. package/components/u-icon/types.ts +69 -69
  78. package/components/u-icon/u-icon.vue +301 -301
  79. package/components/u-image/types.ts +61 -61
  80. package/components/u-image/u-image.vue +245 -245
  81. package/components/u-index-anchor/types.ts +24 -24
  82. package/components/u-index-anchor/u-index-anchor.vue +120 -120
  83. package/components/u-index-list/types.ts +44 -44
  84. package/components/u-index-list/u-index-list.vue +346 -346
  85. package/components/u-input/types.ts +165 -165
  86. package/components/u-input/u-input.vue +453 -453
  87. package/components/u-keyboard/types.ts +40 -40
  88. package/components/u-keyboard/u-keyboard.vue +201 -201
  89. package/components/u-lazy-load/types.ts +37 -37
  90. package/components/u-lazy-load/u-lazy-load.vue +246 -246
  91. package/components/u-line/types.ts +44 -44
  92. package/components/u-line/u-line.vue +68 -68
  93. package/components/u-line-progress/types.ts +58 -58
  94. package/components/u-line-progress/u-line-progress.vue +131 -131
  95. package/components/u-link/types.ts +54 -54
  96. package/components/u-link/u-link.vue +100 -100
  97. package/components/u-loading/types.ts +45 -45
  98. package/components/u-loading/u-loading.vue +106 -106
  99. package/components/u-loading-popup/types.ts +26 -26
  100. package/components/u-loading-popup/u-loading-popup.vue +254 -254
  101. package/components/u-loadmore/types.ts +88 -88
  102. package/components/u-loadmore/u-loadmore.vue +170 -170
  103. package/components/u-mask/types.ts +48 -48
  104. package/components/u-mask/u-mask.vue +113 -113
  105. package/components/u-message-input/types.ts +90 -90
  106. package/components/u-message-input/u-message-input.vue +283 -283
  107. package/components/u-modal/service.ts +48 -48
  108. package/components/u-modal/types.ts +139 -139
  109. package/components/u-modal/u-modal.vue +465 -465
  110. package/components/u-navbar/types.ts +104 -104
  111. package/components/u-navbar/u-navbar.vue +268 -268
  112. package/components/u-no-network/image.ts +2 -2
  113. package/components/u-no-network/types.ts +29 -29
  114. package/components/u-no-network/u-no-network.vue +313 -313
  115. package/components/u-notice-bar/types.ts +111 -111
  116. package/components/u-notice-bar/u-notice-bar.vue +191 -191
  117. package/components/u-number-box/types.ts +42 -42
  118. package/components/u-number-box/u-number-box.vue +322 -322
  119. package/components/u-number-keyboard/types.ts +26 -26
  120. package/components/u-number-keyboard/u-number-keyboard.vue +189 -189
  121. package/components/u-pagination/types.ts +38 -38
  122. package/components/u-pagination/u-pagination.vue +102 -102
  123. package/components/u-picker/types.ts +140 -140
  124. package/components/u-picker/u-picker.vue +854 -854
  125. package/components/u-popup/types.ts +64 -64
  126. package/components/u-popup/u-popup.vue +427 -427
  127. package/components/u-radio/types.ts +39 -39
  128. package/components/u-radio/u-radio.vue +349 -349
  129. package/components/u-radio-group/types.ts +40 -40
  130. package/components/u-radio-group/u-radio-group.vue +96 -96
  131. package/components/u-rate/types.ts +50 -50
  132. package/components/u-rate/u-rate.vue +250 -250
  133. package/components/u-read-more/types.ts +46 -46
  134. package/components/u-read-more/u-read-more.vue +182 -182
  135. package/components/u-root-portal/u-root-portal.vue +55 -55
  136. package/components/u-row/types.ts +30 -30
  137. package/components/u-row/u-row.vue +105 -105
  138. package/components/u-row-notice/types.ts +49 -49
  139. package/components/u-row-notice/u-row-notice.vue +257 -257
  140. package/components/u-safe-bottom/types.ts +19 -19
  141. package/components/u-safe-bottom/u-safe-bottom.vue +55 -55
  142. package/components/u-search/u-search.vue +297 -297
  143. package/components/u-section/types.ts +42 -42
  144. package/components/u-section/u-section.vue +156 -156
  145. package/components/u-select/types.ts +56 -56
  146. package/components/u-select/u-select.vue +447 -447
  147. package/components/u-skeleton/types.ts +89 -89
  148. package/components/u-skeleton/u-skeleton.vue +253 -253
  149. package/components/u-slider/types.ts +55 -55
  150. package/components/u-slider/u-slider.vue +422 -422
  151. package/components/u-status-bar/types.ts +21 -21
  152. package/components/u-status-bar/u-status-bar.vue +64 -64
  153. package/components/u-step/types.ts +37 -37
  154. package/components/u-step/u-step.vue +292 -292
  155. package/components/u-steps/types.ts +39 -39
  156. package/components/u-steps/u-steps.vue +105 -105
  157. package/components/u-sticky/types.ts +33 -33
  158. package/components/u-sticky/u-sticky.vue +177 -177
  159. package/components/u-subsection/types.ts +46 -46
  160. package/components/u-subsection/u-subsection.vue +358 -358
  161. package/components/u-swipe-action/types.ts +60 -60
  162. package/components/u-swipe-action/u-swipe-action.vue +276 -276
  163. package/components/u-swiper/types.ts +57 -57
  164. package/components/u-swiper/u-swiper.vue +308 -308
  165. package/components/u-switch/types.ts +39 -39
  166. package/components/u-switch/u-switch.vue +212 -212
  167. package/components/u-tabbar/types.ts +57 -57
  168. package/components/u-tabbar/u-tabbar.vue +480 -480
  169. package/components/u-table/types.ts +35 -35
  170. package/components/u-table/u-table.vue +67 -67
  171. package/components/u-tabs/types.ts +64 -64
  172. package/components/u-tabs/u-tabs.vue +328 -328
  173. package/components/u-tabs-swiper/types.ts +64 -64
  174. package/components/u-tabs-swiper/u-tabs-swiper.vue +407 -407
  175. package/components/u-tag/types.ts +47 -47
  176. package/components/u-tag/u-tag.vue +276 -276
  177. package/components/u-td/types.ts +22 -22
  178. package/components/u-td/u-td.vue +65 -65
  179. package/components/u-text/types.ts +80 -80
  180. package/components/u-text/u-text.vue +355 -355
  181. package/components/u-textarea/types.ts +105 -105
  182. package/components/u-textarea/u-textarea.vue +450 -450
  183. package/components/u-th/types.ts +22 -22
  184. package/components/u-th/u-th.vue +63 -63
  185. package/components/u-time-line/u-time-line.vue +64 -64
  186. package/components/u-time-line-item/types.ts +24 -24
  187. package/components/u-time-line-item/u-time-line-item.vue +89 -89
  188. package/components/u-toast/service.ts +40 -40
  189. package/components/u-toast/types.ts +54 -54
  190. package/components/u-toast/u-toast.vue +385 -385
  191. package/components/u-top-tips/types.ts +25 -25
  192. package/components/u-top-tips/u-top-tips.vue +130 -130
  193. package/components/u-tr/types.ts +19 -19
  194. package/components/u-tr/u-tr.vue +39 -39
  195. package/components/u-transition/types.ts +43 -43
  196. package/components/u-transition/u-transition.vue +437 -437
  197. package/components/u-upload/types.ts +171 -171
  198. package/components/u-upload/u-upload.vue +1605 -1605
  199. package/components/u-verification-code/types.ts +32 -32
  200. package/components/u-verification-code/u-verification-code.vue +183 -183
  201. package/components/u-waterfall/types.ts +26 -26
  202. package/components/u-waterfall/u-waterfall.vue +188 -188
  203. package/iconfont.css +913 -913
  204. package/index.scss +26 -26
  205. package/libs/config/color.ts +9 -9
  206. package/libs/config/config.ts +59 -59
  207. package/libs/config/theme-tokens.ts +102 -102
  208. package/libs/config/zIndex.ts +32 -32
  209. package/libs/css/color.scss +155 -155
  210. package/libs/css/common.scss +183 -183
  211. package/libs/css/style.components.scss +16 -16
  212. package/libs/css/style.h5.scss +8 -8
  213. package/libs/css/style.mp.scss +68 -68
  214. package/libs/css/style.nvue.scss +15 -15
  215. package/libs/css/style.theme.scss +56 -56
  216. package/libs/css/style.vue.scss +188 -188
  217. package/libs/function/$parent.ts +24 -24
  218. package/libs/function/addUnit.ts +50 -50
  219. package/libs/function/clipboard.ts +73 -73
  220. package/libs/function/color.ts +28 -28
  221. package/libs/function/colorGradient.ts +139 -139
  222. package/libs/function/debounce.ts +28 -28
  223. package/libs/function/deepClone.ts +39 -39
  224. package/libs/function/deepMerge.ts +35 -35
  225. package/libs/function/getParent.ts +63 -63
  226. package/libs/function/getRect.ts +26 -26
  227. package/libs/function/guid.ts +42 -42
  228. package/libs/function/md5.ts +403 -403
  229. package/libs/function/parent.ts +21 -21
  230. package/libs/function/queryParams.ts +64 -64
  231. package/libs/function/random.ts +16 -16
  232. package/libs/function/randomArray.ts +11 -11
  233. package/libs/function/route.ts +118 -118
  234. package/libs/function/styleUtils.ts +83 -83
  235. package/libs/function/sys.ts +15 -15
  236. package/libs/function/test.ts +289 -289
  237. package/libs/function/throttle.ts +31 -31
  238. package/libs/function/timeFormat.ts +55 -55
  239. package/libs/function/timeFrom.ts +48 -48
  240. package/libs/function/toast.ts +14 -14
  241. package/libs/function/trim.ts +21 -21
  242. package/libs/function/type2icon.ts +38 -38
  243. package/libs/hooks/index.ts +10 -10
  244. package/libs/hooks/useColor.ts +61 -61
  245. package/libs/hooks/useCompRelation.ts +424 -424
  246. package/libs/hooks/useDebounce.ts +15 -15
  247. package/libs/hooks/useEmitter.ts +79 -79
  248. package/libs/hooks/useLocale.ts +34 -34
  249. package/libs/hooks/useModal.ts +131 -131
  250. package/libs/hooks/useRect.ts +40 -40
  251. package/libs/hooks/useRouter.ts +173 -173
  252. package/libs/hooks/useTheme.ts +173 -173
  253. package/libs/hooks/useThrottle.ts +16 -16
  254. package/libs/hooks/useToast.ts +115 -115
  255. package/libs/index.ts +349 -349
  256. package/libs/request/auto-http.ts +76 -76
  257. package/libs/request/index.ts +301 -301
  258. package/libs/store/index.ts +88 -88
  259. package/libs/util/async-validator.d.ts +75 -75
  260. package/libs/util/async-validator.js +1 -1
  261. package/libs/util/calendar.d.ts +57 -57
  262. package/libs/util/canvas-2d.ts +182 -182
  263. package/libs/util/config-provider.ts +804 -804
  264. package/libs/util/emitter.ts +112 -112
  265. package/libs/util/mitt.ts +118 -118
  266. package/libs/util/system-theme.ts +25 -25
  267. package/locale/index.ts +2 -2
  268. package/locale/lang/en-US.ts +136 -136
  269. package/locale/lang/zh-CN.ts +136 -136
  270. package/package.json +1 -1
  271. package/plugins/root/page.ts +77 -77
  272. package/plugins/root/root.ts +53 -53
  273. package/theme.scss +149 -149
  274. package/types/components.d.ts +105 -105
  275. package/types/global.d.ts +470 -470
  276. package/types/ignore-errors.d.ts +30 -30
  277. package/types/index.d.ts +15 -15
  278. package/types/uni-app.d.ts +63 -63
@@ -1,328 +1,328 @@
1
- <template>
2
- <view class="u-tabs" :style="$u.toStyle({ background: bgColor }, customStyle)" :class="customClass">
3
- <!-- $u.getRect()对组件根节点无效,因为写了.in(this),故这里获取内层接点尺寸 -->
4
- <view>
5
- <scroll-view
6
- scroll-x
7
- class="u-scroll-view"
8
- :scroll-left="scrollLeft"
9
- :show-scrollbar="false"
10
- scroll-with-animation
11
- >
12
- <view class="u-scroll-box" :id="id" :class="{ 'u-tabs-scroll-flex': !isScroll }">
13
- <view
14
- class="u-tab-item u-line-1"
15
- :class="[item.hidden ? 'u-tab-item-hidden' : '']"
16
- :id="'u-tab-item-' + index"
17
- v-for="(item, index) in list"
18
- :key="index"
19
- @tap="clickTab(index)"
20
- :style="tabItemStyle(index)"
21
- >
22
- <u-badge
23
- :count="item[count] || item['count'] || 0"
24
- :offset="offset"
25
- :is-dot="isDot"
26
- size="mini"
27
- ></u-badge>
28
- {{ item[name] || item['name'] }}
29
- </view>
30
- <view v-if="showBar" class="u-tab-bar" :style="tabBarStyle"></view>
31
- </view>
32
- </scroll-view>
33
- </view>
34
- </view>
35
- </template>
36
-
37
- <script lang="ts">
38
- export default {
39
- name: 'u-tabs',
40
- options: {
41
- addGlobalClass: true,
42
- // #ifndef MP-TOUTIAO
43
- virtualHost: true,
44
- // #endif
45
- styleIsolation: 'shared'
46
- }
47
- };
48
- </script>
49
-
50
- <script setup lang="ts">
51
- import { ref, computed, watch, onMounted, nextTick, getCurrentInstance } from 'vue';
52
- import { $u } from '../..';
53
- import { TabsProps } from './types';
54
- import uBadge from '../u-badge/u-badge.vue';
55
-
56
- /**
57
- * tabs 标签
58
- * @description 该组件,是一个tabs标签组件,在标签多的时候,可以配置为左右滑动,标签少的时候,可以禁止滑动。 该组件的一个特点是配置为滚动模式时,激活的tab会自动移动到组件的中间位置。
59
- * @tutorial https://uviewpro.cn/zh/components/tabs.html
60
- * @property {Boolean} is-scroll tabs是否可以左右拖动(默认true)
61
- * @property {Array} list 标签数组,元素为对象,如[{name: '推荐'}]
62
- * @property {String|Number} current 指定哪个tab为激活状态(默认0)
63
- * @property {String|Number} height 导航栏的高度,单位rpx(默认80)
64
- * @property {String|Number} font-size tab文字大小,单位rpx(默认30)
65
- * @property {String|Number} duration 滑块移动一次所需的时间,单位秒(默认0.5)
66
- * @property {String} active-color 滑块和激活tab文字的颜色(默认主题色primary)
67
- * @property {String} inactive-color tabs文字颜色(默认var(--u-main-color))
68
- * @property {String|Number} bar-width 滑块宽度,单位rpx(默认40)
69
- * @property {Object} active-item-style 活动tabs item的样式,对象形式
70
- * @property {Object} bar-style 底部滑块的样式,对象形式
71
- * @property {Boolean} show-bar 是否显示底部的滑块(默认true)
72
- * @property {String|Number} bar-height 滑块高度,单位rpx(默认6)
73
- * @property {String|Number} item-width 标签的宽度(默认auto)
74
- * @property {String|Number} gutter 单个tab标签的左右内边距之和,单位rpx(默认40)
75
- * @property {String} bg-color tabs导航栏的背景颜色(默认var(--u-bg-white))
76
- * @property {String} name 组件内部读取的list参数中的属性名(tab名称),见官网说明(默认name)
77
- * @property {String} count 组件内部读取的list参数中的属性名(badge徽标数),同name属性的使用,见官网说明(默认count)
78
- * @property {Array} offset 设置badge徽标数的位置偏移,格式为 [x, y],也即设置的为top和right的值,单位rpx(默认[5, 20])
79
- * @property {Boolean} bold 激活选项的字体是否加粗(默认true)
80
- * @event {Function} change 点击标签时触发
81
- * @example <u-tabs ref="tabs" :list="list" :is-scroll="false"></u-tabs>
82
- */
83
-
84
- // props 定义
85
- const props = defineProps(TabsProps);
86
-
87
- /**
88
- * emits 定义
89
- */
90
- const emit = defineEmits(['change']);
91
- const instance = getCurrentInstance();
92
- // 滚动scroll-view的左边滚动距离
93
- const scrollLeft = ref(0);
94
- // 存放对tab菜单查询后的节点信息
95
- const tabQueryInfo = ref<any[]>([]);
96
- // 屏幕宽度,单位为px
97
- const componentWidth = ref(0);
98
- // 移动bar需要通过translateX()移动的距离
99
- const scrollBarLeft = ref(0);
100
- // 父元素(tabs组件)到屏幕左边的距离
101
- const parentLeft = ref(0);
102
- // id值
103
- const id = ref($u.guid());
104
- // 当前活动tab索引
105
- const currentIndex = ref(props.current);
106
- // 滑块第一次移动时(页面刚生成时),无需动画,否则给人怪异的感觉
107
- const barFirstTimeMove = ref(true);
108
-
109
- // 监听list变化,重置索引并重新布局
110
- // 监听tab的变化,重新计算tab菜单的布局信息,因为实际使用中菜单可能是通过
111
- // 后台获取的(如新闻app顶部的菜单),获取返回需要一定时间,所以list变化时,重新获取布局信息
112
- watch(
113
- () => props.list,
114
- (n, o) => {
115
- // list变动时,重制内部索引,否则可能导致超出数组边界的情况
116
- if (n.length !== o.length) currentIndex.value = 0;
117
- // 用$nextTick等待视图更新完毕后再计算tab的局部信息,否则可能因为tab还没生成就获取,就会有问题
118
- nextTick(() => {
119
- init();
120
- });
121
- }
122
- );
123
-
124
- // 监听current变化,自动滚动
125
- watch(
126
- () => props.current,
127
- nVal => {
128
- // 视图更新后再执行移动操作
129
- nextTick(() => {
130
- currentIndex.value = nVal;
131
- scrollByIndex();
132
- });
133
- },
134
- { immediate: true }
135
- );
136
-
137
- // 移动bar的样式
138
- const tabBarStyle = computed(() => {
139
- const style: Record<string, any> = {
140
- width: props.barWidth + 'rpx',
141
- transform: `translate(${scrollBarLeft.value}px, -100%)`,
142
- // 滑块在页面渲染后第一次滑动时,无需动画效果
143
- 'transition-duration': `${barFirstTimeMove.value ? 0 : props.duration}s`,
144
- 'background-color': props.activeColor,
145
- height: props.barHeight + 'rpx',
146
- opacity: barFirstTimeMove.value ? 0 : 1,
147
- // 设置一个很大的值,它会自动取能用的最大值,不用高度的一半,是因为高度可能是单数,会有小数出现
148
- 'border-radius': `${Number(props.barHeight) / 2}px`
149
- };
150
- Object.assign(style, props.barStyle);
151
- return style;
152
- });
153
-
154
- // tab的样式
155
- function tabItemStyle(index: number) {
156
- let style: Record<string, any> = {
157
- height: props.height + 'rpx',
158
- 'line-height': props.height + 'rpx',
159
- 'font-size': props.fontSize + 'rpx',
160
- 'transition-duration': `${props.duration}s`,
161
- padding: props.isScroll ? `0 ${props.gutter}rpx` : '',
162
- flex: props.isScroll ? 'auto' : '1',
163
- width: $u.addUnit(props.itemWidth)
164
- };
165
- // 字体加粗
166
- if (index == Number(currentIndex.value) && props.bold) style.fontWeight = 'bold';
167
- if (index == Number(currentIndex.value)) {
168
- style.color = props.activeColor;
169
- // 给选中的tab item添加外部自定义的样式
170
- style = Object.assign(style, props.activeItemStyle);
171
- } else {
172
- style.color = props.inactiveColor;
173
- }
174
- return style;
175
- }
176
-
177
- /**
178
- * 初始化tab布局信息
179
- */
180
- async function init() {
181
- // 获取tabs组件的尺寸信息
182
- const tabRect = await $u.getRect('#' + id.value, instance);
183
- // tabs组件距离屏幕左边的宽度
184
- parentLeft.value = tabRect.left;
185
- // tabs组件的宽度
186
- componentWidth.value = tabRect.width;
187
- getTabRect();
188
- }
189
-
190
- /**
191
- * 点击某一个tab菜单
192
- */
193
- function clickTab(index: number) {
194
- // 点击当前活动tab,不触发事件
195
- if (index == currentIndex.value) return;
196
- // 发送事件给父组件
197
- emit('change', index);
198
- }
199
-
200
- /**
201
- * 查询tab的布局信息
202
- */
203
- function getTabRect() {
204
- // 创建节点查询
205
- const query = uni.createSelectorQuery().in(instance?.proxy);
206
- // 历遍所有tab,这里是执行了查询,最终使用exec()会一次性返回查询的数组结果
207
- for (let i = 0; i < props.list.length; i++) {
208
- // 只要size和rect两个参数
209
- query.select(`#u-tab-item-${i}`).fields({ size: true, rect: true }, () => {});
210
- }
211
- // 执行查询,一次性获取多个结果
212
- query.exec((res: any[]) => {
213
- tabQueryInfo.value = res;
214
- // 初始化滚动条和移动bar的位置
215
- scrollByIndex();
216
- });
217
- }
218
-
219
- /**
220
- * 滚动scroll-view,让活动的tab处于屏幕的中间位置
221
- */
222
- function scrollByIndex() {
223
- // 当前活动tab的布局信息,有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息
224
- const tabInfo = tabQueryInfo.value[Number(currentIndex.value)];
225
- if (!tabInfo) return;
226
- // 活动tab的宽度
227
- const tabWidth = tabInfo.width;
228
- // 活动item的左边到tabs组件左边的距离,用item的left减去tabs的left
229
- const offsetLeft = tabInfo.left - parentLeft.value;
230
- // 将活动的tabs-item移动到屏幕正中间,实际上是对scroll-view的移动
231
- const scrollL = offsetLeft - (componentWidth.value - tabWidth) / 2;
232
- scrollLeft.value = scrollL < 0 ? 0 : scrollL;
233
- // 当前活动item的中点点到左边的距离减去滑块宽度的一半,即可得到滑块所需的移动距离
234
- const left = tabInfo.left + tabInfo.width / 2 - parentLeft.value;
235
- // 计算当前活跃item到组件左边的距离
236
- scrollBarLeft.value = left - uni.upx2px(Number(props.barWidth)) / 2;
237
- // 第一次移动滑块的时候,barFirstTimeMove为true,放到延时中将其设置false
238
- // 延时是因为scrollBarLeft作用于computed计算时,需要一个过程需,否则导致出错
239
- if (barFirstTimeMove.value) {
240
- setTimeout(() => {
241
- barFirstTimeMove.value = false;
242
- }, 100);
243
- }
244
- }
245
-
246
- onMounted(() => {
247
- nextTick(() => {
248
- // 延时获取tabs的尺寸信息
249
- setTimeout(() => {
250
- init();
251
- }, 500);
252
- });
253
- });
254
-
255
- defineExpose({ init, clickTab, scrollByIndex });
256
- </script>
257
-
258
- <style lang="scss" scoped>
259
- @import '../../libs/css/style.components.scss';
260
-
261
- view,
262
- scroll-view {
263
- box-sizing: border-box;
264
- }
265
-
266
- // 隐藏滚动条样式,支持App、H5、小程序等平台
267
- ::-webkit-scrollbar {
268
- display: none;
269
- width: 0 !important;
270
- height: 0 !important;
271
- -webkit-appearance: none;
272
- background: transparent;
273
- }
274
-
275
- .u-scroll-box {
276
- position: relative;
277
- /* #ifdef MP-TOUTIAO */
278
- white-space: nowrap;
279
- /* #endif */
280
- }
281
-
282
- /* #ifdef H5 */
283
- // 通过样式穿透,隐藏H5下,scroll-view下的滚动条
284
- scroll-view ::v-deep ::-webkit-scrollbar {
285
- display: none;
286
- width: 0 !important;
287
- height: 0 !important;
288
- -webkit-appearance: none;
289
- background: transparent;
290
- }
291
- /* #endif */
292
-
293
- // App-nvue 平台使用特殊的滚动条隐藏方式
294
- /* #ifdef APP-NVUE */
295
- .scroll-view-nvue {
296
- -webkit-scrollbar: none;
297
- }
298
- /* #endif */
299
-
300
- .u-scroll-view {
301
- width: 100%;
302
- white-space: nowrap;
303
- position: relative;
304
- }
305
-
306
- .u-tab-item {
307
- position: relative;
308
- /* #ifndef APP-NVUE */
309
- display: inline-block;
310
- /* #endif */
311
- text-align: center;
312
- transition-property: background-color, color;
313
- }
314
-
315
- .u-tab-item-hidden {
316
- display: none;
317
- }
318
-
319
- .u-tab-bar {
320
- position: absolute;
321
- bottom: 0;
322
- }
323
-
324
- .u-tabs-scroll-flex {
325
- @include vue-flex;
326
- justify-content: space-between;
327
- }
328
- </style>
1
+ <template>
2
+ <view class="u-tabs" :style="$u.toStyle({ background: bgColor }, customStyle)" :class="customClass">
3
+ <!-- $u.getRect()对组件根节点无效,因为写了.in(this),故这里获取内层接点尺寸 -->
4
+ <view>
5
+ <scroll-view
6
+ scroll-x
7
+ class="u-scroll-view"
8
+ :scroll-left="scrollLeft"
9
+ :show-scrollbar="false"
10
+ scroll-with-animation
11
+ >
12
+ <view class="u-scroll-box" :id="id" :class="{ 'u-tabs-scroll-flex': !isScroll }">
13
+ <view
14
+ class="u-tab-item u-line-1"
15
+ :class="[item.hidden ? 'u-tab-item-hidden' : '']"
16
+ :id="'u-tab-item-' + index"
17
+ v-for="(item, index) in list"
18
+ :key="index"
19
+ @tap="clickTab(index)"
20
+ :style="tabItemStyle(index)"
21
+ >
22
+ <u-badge
23
+ :count="item[count] || item['count'] || 0"
24
+ :offset="offset"
25
+ :is-dot="isDot"
26
+ size="mini"
27
+ ></u-badge>
28
+ {{ item[name] || item['name'] }}
29
+ </view>
30
+ <view v-if="showBar" class="u-tab-bar" :style="tabBarStyle"></view>
31
+ </view>
32
+ </scroll-view>
33
+ </view>
34
+ </view>
35
+ </template>
36
+
37
+ <script lang="ts">
38
+ export default {
39
+ name: 'u-tabs',
40
+ options: {
41
+ addGlobalClass: true,
42
+ // #ifndef MP-TOUTIAO
43
+ virtualHost: true,
44
+ // #endif
45
+ styleIsolation: 'shared'
46
+ }
47
+ };
48
+ </script>
49
+
50
+ <script setup lang="ts">
51
+ import { ref, computed, watch, onMounted, nextTick, getCurrentInstance } from 'vue';
52
+ import { $u } from '../..';
53
+ import { TabsProps } from './types';
54
+ import uBadge from '../u-badge/u-badge.vue';
55
+
56
+ /**
57
+ * tabs 标签
58
+ * @description 该组件,是一个tabs标签组件,在标签多的时候,可以配置为左右滑动,标签少的时候,可以禁止滑动。 该组件的一个特点是配置为滚动模式时,激活的tab会自动移动到组件的中间位置。
59
+ * @tutorial https://uviewpro.cn/zh/components/tabs.html
60
+ * @property {Boolean} is-scroll tabs是否可以左右拖动(默认true)
61
+ * @property {Array} list 标签数组,元素为对象,如[{name: '推荐'}]
62
+ * @property {String|Number} current 指定哪个tab为激活状态(默认0)
63
+ * @property {String|Number} height 导航栏的高度,单位rpx(默认80)
64
+ * @property {String|Number} font-size tab文字大小,单位rpx(默认30)
65
+ * @property {String|Number} duration 滑块移动一次所需的时间,单位秒(默认0.5)
66
+ * @property {String} active-color 滑块和激活tab文字的颜色(默认主题色primary)
67
+ * @property {String} inactive-color tabs文字颜色(默认var(--u-main-color))
68
+ * @property {String|Number} bar-width 滑块宽度,单位rpx(默认40)
69
+ * @property {Object} active-item-style 活动tabs item的样式,对象形式
70
+ * @property {Object} bar-style 底部滑块的样式,对象形式
71
+ * @property {Boolean} show-bar 是否显示底部的滑块(默认true)
72
+ * @property {String|Number} bar-height 滑块高度,单位rpx(默认6)
73
+ * @property {String|Number} item-width 标签的宽度(默认auto)
74
+ * @property {String|Number} gutter 单个tab标签的左右内边距之和,单位rpx(默认40)
75
+ * @property {String} bg-color tabs导航栏的背景颜色(默认var(--u-bg-white))
76
+ * @property {String} name 组件内部读取的list参数中的属性名(tab名称),见官网说明(默认name)
77
+ * @property {String} count 组件内部读取的list参数中的属性名(badge徽标数),同name属性的使用,见官网说明(默认count)
78
+ * @property {Array} offset 设置badge徽标数的位置偏移,格式为 [x, y],也即设置的为top和right的值,单位rpx(默认[5, 20])
79
+ * @property {Boolean} bold 激活选项的字体是否加粗(默认true)
80
+ * @event {Function} change 点击标签时触发
81
+ * @example <u-tabs ref="tabs" :list="list" :is-scroll="false"></u-tabs>
82
+ */
83
+
84
+ // props 定义
85
+ const props = defineProps(TabsProps);
86
+
87
+ /**
88
+ * emits 定义
89
+ */
90
+ const emit = defineEmits(['change']);
91
+ const instance = getCurrentInstance();
92
+ // 滚动scroll-view的左边滚动距离
93
+ const scrollLeft = ref(0);
94
+ // 存放对tab菜单查询后的节点信息
95
+ const tabQueryInfo = ref<any[]>([]);
96
+ // 屏幕宽度,单位为px
97
+ const componentWidth = ref(0);
98
+ // 移动bar需要通过translateX()移动的距离
99
+ const scrollBarLeft = ref(0);
100
+ // 父元素(tabs组件)到屏幕左边的距离
101
+ const parentLeft = ref(0);
102
+ // id值
103
+ const id = ref($u.guid());
104
+ // 当前活动tab索引
105
+ const currentIndex = ref(props.current);
106
+ // 滑块第一次移动时(页面刚生成时),无需动画,否则给人怪异的感觉
107
+ const barFirstTimeMove = ref(true);
108
+
109
+ // 监听list变化,重置索引并重新布局
110
+ // 监听tab的变化,重新计算tab菜单的布局信息,因为实际使用中菜单可能是通过
111
+ // 后台获取的(如新闻app顶部的菜单),获取返回需要一定时间,所以list变化时,重新获取布局信息
112
+ watch(
113
+ () => props.list,
114
+ (n, o) => {
115
+ // list变动时,重制内部索引,否则可能导致超出数组边界的情况
116
+ if (n.length !== o.length) currentIndex.value = 0;
117
+ // 用$nextTick等待视图更新完毕后再计算tab的局部信息,否则可能因为tab还没生成就获取,就会有问题
118
+ nextTick(() => {
119
+ init();
120
+ });
121
+ }
122
+ );
123
+
124
+ // 监听current变化,自动滚动
125
+ watch(
126
+ () => props.current,
127
+ nVal => {
128
+ // 视图更新后再执行移动操作
129
+ nextTick(() => {
130
+ currentIndex.value = nVal;
131
+ scrollByIndex();
132
+ });
133
+ },
134
+ { immediate: true }
135
+ );
136
+
137
+ // 移动bar的样式
138
+ const tabBarStyle = computed(() => {
139
+ const style: Record<string, any> = {
140
+ width: props.barWidth + 'rpx',
141
+ transform: `translate(${scrollBarLeft.value}px, -100%)`,
142
+ // 滑块在页面渲染后第一次滑动时,无需动画效果
143
+ 'transition-duration': `${barFirstTimeMove.value ? 0 : props.duration}s`,
144
+ 'background-color': props.activeColor,
145
+ height: props.barHeight + 'rpx',
146
+ opacity: barFirstTimeMove.value ? 0 : 1,
147
+ // 设置一个很大的值,它会自动取能用的最大值,不用高度的一半,是因为高度可能是单数,会有小数出现
148
+ 'border-radius': `${Number(props.barHeight) / 2}px`
149
+ };
150
+ Object.assign(style, props.barStyle);
151
+ return style;
152
+ });
153
+
154
+ // tab的样式
155
+ function tabItemStyle(index: number) {
156
+ let style: Record<string, any> = {
157
+ height: props.height + 'rpx',
158
+ 'line-height': props.height + 'rpx',
159
+ 'font-size': props.fontSize + 'rpx',
160
+ 'transition-duration': `${props.duration}s`,
161
+ padding: props.isScroll ? `0 ${props.gutter}rpx` : '',
162
+ flex: props.isScroll ? 'auto' : '1',
163
+ width: $u.addUnit(props.itemWidth)
164
+ };
165
+ // 字体加粗
166
+ if (index == Number(currentIndex.value) && props.bold) style.fontWeight = 'bold';
167
+ if (index == Number(currentIndex.value)) {
168
+ style.color = props.activeColor;
169
+ // 给选中的tab item添加外部自定义的样式
170
+ style = Object.assign(style, props.activeItemStyle);
171
+ } else {
172
+ style.color = props.inactiveColor;
173
+ }
174
+ return style;
175
+ }
176
+
177
+ /**
178
+ * 初始化tab布局信息
179
+ */
180
+ async function init() {
181
+ // 获取tabs组件的尺寸信息
182
+ const tabRect = await $u.getRect('#' + id.value, instance);
183
+ // tabs组件距离屏幕左边的宽度
184
+ parentLeft.value = tabRect.left;
185
+ // tabs组件的宽度
186
+ componentWidth.value = tabRect.width;
187
+ getTabRect();
188
+ }
189
+
190
+ /**
191
+ * 点击某一个tab菜单
192
+ */
193
+ function clickTab(index: number) {
194
+ // 点击当前活动tab,不触发事件
195
+ if (index == currentIndex.value) return;
196
+ // 发送事件给父组件
197
+ emit('change', index);
198
+ }
199
+
200
+ /**
201
+ * 查询tab的布局信息
202
+ */
203
+ function getTabRect() {
204
+ // 创建节点查询
205
+ const query = uni.createSelectorQuery().in(instance?.proxy);
206
+ // 历遍所有tab,这里是执行了查询,最终使用exec()会一次性返回查询的数组结果
207
+ for (let i = 0; i < props.list.length; i++) {
208
+ // 只要size和rect两个参数
209
+ query.select(`#u-tab-item-${i}`).fields({ size: true, rect: true }, () => {});
210
+ }
211
+ // 执行查询,一次性获取多个结果
212
+ query.exec((res: any[]) => {
213
+ tabQueryInfo.value = res;
214
+ // 初始化滚动条和移动bar的位置
215
+ scrollByIndex();
216
+ });
217
+ }
218
+
219
+ /**
220
+ * 滚动scroll-view,让活动的tab处于屏幕的中间位置
221
+ */
222
+ function scrollByIndex() {
223
+ // 当前活动tab的布局信息,有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息
224
+ const tabInfo = tabQueryInfo.value[Number(currentIndex.value)];
225
+ if (!tabInfo) return;
226
+ // 活动tab的宽度
227
+ const tabWidth = tabInfo.width;
228
+ // 活动item的左边到tabs组件左边的距离,用item的left减去tabs的left
229
+ const offsetLeft = tabInfo.left - parentLeft.value;
230
+ // 将活动的tabs-item移动到屏幕正中间,实际上是对scroll-view的移动
231
+ const scrollL = offsetLeft - (componentWidth.value - tabWidth) / 2;
232
+ scrollLeft.value = scrollL < 0 ? 0 : scrollL;
233
+ // 当前活动item的中点点到左边的距离减去滑块宽度的一半,即可得到滑块所需的移动距离
234
+ const left = tabInfo.left + tabInfo.width / 2 - parentLeft.value;
235
+ // 计算当前活跃item到组件左边的距离
236
+ scrollBarLeft.value = left - uni.upx2px(Number(props.barWidth)) / 2;
237
+ // 第一次移动滑块的时候,barFirstTimeMove为true,放到延时中将其设置false
238
+ // 延时是因为scrollBarLeft作用于computed计算时,需要一个过程需,否则导致出错
239
+ if (barFirstTimeMove.value) {
240
+ setTimeout(() => {
241
+ barFirstTimeMove.value = false;
242
+ }, 100);
243
+ }
244
+ }
245
+
246
+ onMounted(() => {
247
+ nextTick(() => {
248
+ // 延时获取tabs的尺寸信息
249
+ setTimeout(() => {
250
+ init();
251
+ }, 500);
252
+ });
253
+ });
254
+
255
+ defineExpose({ init, clickTab, scrollByIndex });
256
+ </script>
257
+
258
+ <style lang="scss" scoped>
259
+ @import '../../libs/css/style.components.scss';
260
+
261
+ view,
262
+ scroll-view {
263
+ box-sizing: border-box;
264
+ }
265
+
266
+ // 隐藏滚动条样式,支持App、H5、小程序等平台
267
+ ::-webkit-scrollbar {
268
+ display: none;
269
+ width: 0 !important;
270
+ height: 0 !important;
271
+ -webkit-appearance: none;
272
+ background: transparent;
273
+ }
274
+
275
+ .u-scroll-box {
276
+ position: relative;
277
+ /* #ifdef MP-TOUTIAO */
278
+ white-space: nowrap;
279
+ /* #endif */
280
+ }
281
+
282
+ /* #ifdef H5 */
283
+ // 通过样式穿透,隐藏H5下,scroll-view下的滚动条
284
+ scroll-view ::v-deep ::-webkit-scrollbar {
285
+ display: none;
286
+ width: 0 !important;
287
+ height: 0 !important;
288
+ -webkit-appearance: none;
289
+ background: transparent;
290
+ }
291
+ /* #endif */
292
+
293
+ // App-nvue 平台使用特殊的滚动条隐藏方式
294
+ /* #ifdef APP-NVUE */
295
+ .scroll-view-nvue {
296
+ -webkit-scrollbar: none;
297
+ }
298
+ /* #endif */
299
+
300
+ .u-scroll-view {
301
+ width: 100%;
302
+ white-space: nowrap;
303
+ position: relative;
304
+ }
305
+
306
+ .u-tab-item {
307
+ position: relative;
308
+ /* #ifndef APP-NVUE */
309
+ display: inline-block;
310
+ /* #endif */
311
+ text-align: center;
312
+ transition-property: background-color, color;
313
+ }
314
+
315
+ .u-tab-item-hidden {
316
+ display: none;
317
+ }
318
+
319
+ .u-tab-bar {
320
+ position: absolute;
321
+ bottom: 0;
322
+ }
323
+
324
+ .u-tabs-scroll-flex {
325
+ @include vue-flex;
326
+ justify-content: space-between;
327
+ }
328
+ </style>