From 627c3e0a6920131d75eafa4646db373ccc936546 Mon Sep 17 00:00:00 2001
From: jiangping <jp@doumee.com>
Date: 星期四, 26 十月 2023 13:52:07 +0800
Subject: [PATCH] 小程序diamante
---
minipro_standard/uni_modules/uview-ui/components/u-tabs/u-tabs.vue | 354 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 354 insertions(+), 0 deletions(-)
diff --git a/minipro_standard/uni_modules/uview-ui/components/u-tabs/u-tabs.vue b/minipro_standard/uni_modules/uview-ui/components/u-tabs/u-tabs.vue
new file mode 100644
index 0000000..9c54cc1
--- /dev/null
+++ b/minipro_standard/uni_modules/uview-ui/components/u-tabs/u-tabs.vue
@@ -0,0 +1,354 @@
+<template>
+ <view class="u-tabs">
+ <view class="u-tabs__wrapper">
+ <slot name="left" />
+ <view class="u-tabs__wrapper__scroll-view-wrapper">
+ <scroll-view
+ :scroll-x="scrollable"
+ :scroll-left="scrollLeft"
+ scroll-with-animation
+ class="u-tabs__wrapper__scroll-view"
+ :show-scrollbar="false"
+ ref="u-tabs__wrapper__scroll-view"
+ >
+ <view
+ class="u-tabs__wrapper__nav"
+ ref="u-tabs__wrapper__nav"
+ >
+ <view
+ class="u-tabs__wrapper__nav__item"
+ v-for="(item, index) in list"
+ :key="index"
+ @tap="clickHandler(item, index)"
+ :ref="`u-tabs__wrapper__nav__item-${index}`"
+ :style="[$u.addStyle(itemStyle), {flex: scrollable ? '' : 1}]"
+ :class="[`u-tabs__wrapper__nav__item-${index}`, item.disabled && 'u-tabs__wrapper__nav__item--disabled']"
+ >
+ <text
+ :class="[item.disabled && 'u-tabs__wrapper__nav__item__text--disabled']"
+ class="u-tabs__wrapper__nav__item__text"
+ :style="[textStyle(index)]"
+ >{{ item[keyName] }}</text>
+ <u-badge
+ :show="!!(item.badge && (item.badge.show || item.badge.isDot || item.badge.value))"
+ :isDot="item.badge && item.badge.isDot || propsBadge.isDot"
+ :value="item.badge && item.badge.value || propsBadge.value"
+ :max="item.badge && item.badge.max || propsBadge.max"
+ :type="item.badge && item.badge.type || propsBadge.type"
+ :showZero="item.badge && item.badge.showZero || propsBadge.showZero"
+ :bgColor="item.badge && item.badge.bgColor || propsBadge.bgColor"
+ :color="item.badge && item.badge.color || propsBadge.color"
+ :shape="item.badge && item.badge.shape || propsBadge.shape"
+ :numberType="item.badge && item.badge.numberType || propsBadge.numberType"
+ :inverted="item.badge && item.badge.inverted || propsBadge.inverted"
+ customStyle="margin-left: 4px;"
+ ></u-badge>
+ </view>
+ <!-- #ifdef APP-NVUE -->
+ <view
+ class="u-tabs__wrapper__nav__line"
+ ref="u-tabs__wrapper__nav__line"
+ :style="[{
+ width: $u.addUnit(lineWidth),
+ height: $u.addUnit(lineHeight),
+ background: lineColor,
+ backgroundSize: lineBgSize,
+ }]"
+ >
+ <!-- #endif -->
+ <!-- #ifndef APP-NVUE -->
+ <view
+ class="u-tabs__wrapper__nav__line"
+ ref="u-tabs__wrapper__nav__line"
+ :style="[{
+ width: $u.addUnit(lineWidth),
+ transform: `translate(${lineOffsetLeft}px)`,
+ transitionDuration: `${firstTime ? 0 : duration}ms`,
+ height: $u.addUnit(lineHeight),
+ background: lineColor,
+ backgroundSize: lineBgSize,
+ }]"
+ >
+ <!-- #endif -->
+ </view>
+ </view>
+ </scroll-view>
+ </view>
+ <slot name="right" />
+ </view>
+ </view>
+</template>
+
+<script>
+ // #ifdef APP-NVUE
+ const animation = uni.requireNativePlugin('animation')
+ const dom = uni.requireNativePlugin('dom')
+ // #endif
+ import props from './props.js';
+ /**
+ * Tabs 鏍囩
+ * @description tabs鏍囩缁勪欢锛屽湪鏍囩澶氱殑鏃跺�欙紝鍙互閰嶇疆涓哄乏鍙虫粦鍔紝鏍囩灏戠殑鏃跺�欙紝鍙互绂佹婊戝姩銆� 璇ョ粍浠剁殑涓�涓壒鐐规槸閰嶇疆涓烘粴鍔ㄦā寮忔椂锛屾縺娲荤殑tab浼氳嚜鍔ㄧЩ鍔ㄥ埌缁勪欢鐨勪腑闂翠綅缃��
+ * @tutorial https://www.uviewui.com/components/tabs.html
+ * @property {String | Number} duration 婊戝潡绉诲姩涓�娆℃墍闇�鐨勬椂闂达紝鍗曚綅绉掞紙榛樿 200 锛�
+ * @property {String | Number} swierWidth swiper鐨勫搴︼紙榛樿 '750rpx' 锛�
+ * @property {String} keyName 浠巂list`鍏冪礌瀵硅薄涓鍙栫殑閿悕锛堥粯璁� 'name' 锛�
+ * @event {Function(index)} change 鏍囩鏀瑰彉鏃惰Е鍙� index: 鐐瑰嚮浜嗙鍑犱釜tab锛岀储寮曚粠0寮�濮�
+ * @event {Function(index)} click 鐐瑰嚮鏍囩鏃惰Е鍙� index: 鐐瑰嚮浜嗙鍑犱釜tab锛岀储寮曚粠0寮�濮�
+ * @example <u-tabs :list="list" :is-scroll="false" :current="current" @change="change"></u-tabs>
+ */
+ export default {
+ name: 'u-tabs',
+ mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
+ data() {
+ return {
+ firstTime: true,
+ scrollLeft: 0,
+ scrollViewWidth: 0,
+ lineOffsetLeft: 0,
+ tabsRect: {
+ left: 0
+ },
+ innerCurrent: 0,
+ moving: false,
+ }
+ },
+ watch: {
+ current: {
+ immediate: true,
+ handler (newValue, oldValue) {
+ // 鍐呭閮ㄥ�间笉鐩哥瓑鏃讹紝鎵嶅皾璇曠Щ鍔ㄦ粦鍧�
+ if (newValue !== this.innerCurrent) {
+ this.innerCurrent = newValue
+ this.$nextTick(() => {
+ this.resize()
+ })
+ }
+ }
+ },
+ // list鍙樺寲鏃讹紝閲嶆柊娓叉煋list鍚勯」淇℃伅
+ list() {
+ this.$nextTick(() => {
+ this.resize()
+ })
+ }
+ },
+ computed: {
+ textStyle() {
+ return index => {
+ const style = {}
+ // 鍙栧綋鏈熸槸鍚︽縺娲荤殑鏍峰紡
+ const customeStyle = index === this.innerCurrent ? uni.$u.addStyle(this.activeStyle) : uni.$u
+ .addStyle(
+ this.inactiveStyle)
+ // 濡傛灉褰撳墠鑿滃崟琚鐢紝鍒欏姞涓婂搴旈鑹诧紝闇�瑕佸湪姝ゅ仛澶勭悊锛屾槸鍥犱负nvue涓嬶紝鏃犳硶鍦╯tyle鏍峰紡涓�氳繃!import瑕嗙洊鏍囩鐨勫唴鑱旀牱寮�
+ if (this.list[index].disabled) {
+ style.color = '#c8c9cc'
+ }
+ return uni.$u.deepMerge(customeStyle, style)
+ }
+ },
+ propsBadge() {
+ return uni.$u.props.badge
+ }
+ },
+ async mounted() {
+ this.init()
+ },
+ methods: {
+ setLineLeft() {
+ const tabItem = this.list[this.innerCurrent];
+ if (!tabItem) {
+ return;
+ }
+ // 鑾峰彇婊戝潡璇ョЩ鍔ㄧ殑浣嶇疆
+ let lineOffsetLeft = this.list
+ .slice(0, this.innerCurrent)
+ .reduce((total, curr) => total + curr.rect.width, 0);
+ // 鑾峰彇涓嬪垝绾跨殑鏁板�紁x琛ㄧず娉�
+ const lineWidth = uni.$u.getPx(this.lineWidth);
+ this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2
+ // #ifdef APP-NVUE
+ // 绗竴娆$Щ鍔ㄦ粦鍧楋紝鏃犻渶杩囨浮鏃堕棿
+ this.animation(this.lineOffsetLeft, this.firstTime ? 0 : parseInt(this.duration))
+ // #endif
+
+ // 濡傛灉鏄涓�娆℃墽琛屾鏂规硶锛岃婊戝潡鍦ㄥ垵濮嬪寲鏃讹紝鐬棿婊戝姩鍒扮涓�涓猼ab item鐨勪腑闂�
+ // 杩欓噷闇�瑕佷竴涓畾鏃跺櫒锛屽洜涓哄湪闈瀗vue涓嬶紝鏄洿鎺ラ�氳繃style缁戝畾杩囨浮鏃堕棿锛岄渶瑕佺瓑鍏惰繃娓″畬鎴愬悗锛屽啀璁剧疆涓篺alse(闈炵涓�娆$Щ鍔ㄦ粦鍧�)
+ if (this.firstTime) {
+ setTimeout(() => {
+ this.firstTime = false
+ }, 10);
+ }
+ },
+ // nvue涓嬭缃粦鍧楃殑浣嶇疆
+ animation(x, duration = 0) {
+ // #ifdef APP-NVUE
+ const ref = this.$refs['u-tabs__wrapper__nav__line']
+ animation.transition(ref, {
+ styles: {
+ transform: `translateX(${x}px)`
+ },
+ duration
+ })
+ // #endif
+ },
+ // 鐐瑰嚮鏌愪竴涓爣绛�
+ clickHandler(item, index) {
+ // 鍥犱负鏍囩鍙兘涓篸isabled鐘舵�侊紝鎵�浠lick鏄竴瀹氫細鍙戝嚭鐨勶紝浣嗘槸change浜嬩欢鏄渶瑕佸彲鐢ㄧ殑鐘舵�佹墠鍙戝嚭
+ this.$emit('click', {
+ ...item,
+ index
+ })
+ // 濡傛灉disabled鐘舵�侊紝杩斿洖
+ if (item.disabled) return
+ this.innerCurrent = index
+ this.resize()
+ this.$emit('change', {
+ ...item,
+ index
+ })
+ },
+ init() {
+ uni.$u.sleep().then(() => {
+ this.resize()
+ })
+ },
+ setScrollLeft() {
+ // 褰撳墠娲诲姩tab鐨勫竷灞�淇℃伅锛屾湁tab鑿滃崟鐨剋idth鍜宭eft(涓哄厓绱犲乏杈圭晫鍒扮埗鍏冪礌宸﹁竟鐣岀殑璺濈)绛変俊鎭�
+ const tabRect = this.list[this.innerCurrent]
+ // 绱姞寰楀埌褰撳墠item鍒板乏杈圭殑璺濈
+ const offsetLeft = this.list
+ .slice(0, this.innerCurrent)
+ .reduce((total, curr) => {
+ return total + curr.rect.width
+ }, 0)
+ // 姝ゅ涓哄睆骞曞搴�
+ const windowWidth = uni.$u.sys().windowWidth
+ // 灏嗘椿鍔ㄧ殑tabs-item绉诲姩鍒板睆骞曟涓棿锛屽疄闄呬笂鏄scroll-view鐨勭Щ鍔�
+ let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect
+ .right) / 2 + this.tabsRect.left / 2
+ // 杩欓噷鍋氫竴涓檺鍒讹紝闄愬埗scrollLeft鐨勬渶澶у�间负鏁翠釜scroll-view瀹藉害鍑忓幓tabs缁勪欢鐨勫搴�
+ scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width)
+ this.scrollLeft = Math.max(0, scrollLeft)
+ },
+ // 鑾峰彇鎵�鏈夋爣绛剧殑灏哄
+ resize() {
+ // 濡傛灉涓嶅瓨鍦╨ist锛屽垯涓嶅鐞�
+ if(this.list.length === 0) {
+ return
+ }
+ Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => {
+ this.tabsRect = tabsRect
+ this.scrollViewWidth = 0
+ itemRect.map((item, index) => {
+ // 璁$畻scroll-view鐨勫搴︼紝杩欓噷
+ this.scrollViewWidth += item.width
+ // 鍙﹀璁$畻姣忎竴涓猧tem鐨勪腑蹇冪偣X杞村潗鏍�
+ this.list[index].rect = item
+ })
+ // 鑾峰彇浜唗abs鐨勫昂瀵镐箣鍚庯紝璁剧疆婊戝潡鐨勪綅缃�
+ this.setLineLeft()
+ this.setScrollLeft()
+ })
+ },
+ // 鑾峰彇瀵艰埅鑿滃崟鐨勫昂瀵�
+ getTabsRect() {
+ return new Promise(resolve => {
+ this.queryRect('u-tabs__wrapper__scroll-view').then(size => resolve(size))
+ })
+ },
+ // 鑾峰彇鎵�鏈夋爣绛剧殑灏哄
+ getAllItemRect() {
+ return new Promise(resolve => {
+ const promiseAllArr = this.list.map((item, index) => this.queryRect(
+ `u-tabs__wrapper__nav__item-${index}`, true))
+ Promise.all(promiseAllArr).then(sizes => resolve(sizes))
+ })
+ },
+ // 鑾峰彇鍚勪釜鏍囩鐨勫昂瀵�
+ queryRect(el, item) {
+ // #ifndef APP-NVUE
+ // $uGetRect涓簎View鑷甫鐨勮妭鐐规煡璇㈢畝鍖栨柟娉曪紝璇﹁鏂囨。浠嬬粛锛歨ttps://www.uviewui.com/js/getRect.html
+ // 缁勪欢鍐呴儴涓�鑸敤this.$uGetRect锛屽澶栫殑涓簎ni.$u.getRect锛屼簩鑰呭姛鑳戒竴鑷达紝鍚嶇О涓嶅悓
+ return new Promise(resolve => {
+ this.$uGetRect(`.${el}`).then(size => {
+ resolve(size)
+ })
+ })
+ // #endif
+
+ // #ifdef APP-NVUE
+ // nvue涓嬶紝浣跨敤dom妯″潡鏌ヨ鍏冪礌楂樺害
+ // 杩斿洖涓�涓猵romise锛岃璋冪敤姝ゆ柟娉曠殑涓讳綋鑳戒娇鐢╰hen鍥炶皟
+ return new Promise(resolve => {
+ dom.getComponentRect(item ? this.$refs[el][0] : this.$refs[el], res => {
+ resolve(res.size)
+ })
+ })
+ // #endif
+ },
+ },
+ }
+</script>
+
+<style lang="scss" scoped>
+ @import "../../libs/css/components.scss";
+
+ .u-tabs {
+
+ &__wrapper {
+ @include flex;
+ align-items: center;
+
+ &__scroll-view-wrapper {
+ flex: 1;
+ /* #ifndef APP-NVUE */
+ overflow: auto hidden;
+ /* #endif */
+ }
+
+ &__scroll-view {
+ @include flex;
+ flex: 1;
+ }
+
+ &__nav {
+ @include flex;
+ position: relative;
+
+ &__item {
+ padding: 0 11px;
+ @include flex;
+ align-items: center;
+ justify-content: center;
+
+ &--disabled {
+ /* #ifndef APP-NVUE */
+ cursor: not-allowed;
+ /* #endif */
+ }
+
+ &__text {
+ font-size: 15px;
+ color: $u-content-color;
+
+ &--disabled {
+ color: $u-disabled-color !important;
+ }
+ }
+ }
+
+ &__line {
+ height: 3px;
+ background: $u-primary;
+ width: 30px;
+ position: absolute;
+ bottom: 2px;
+ border-radius: 100px;
+ transition-property: transform;
+ transition-duration: 300ms;
+ }
+ }
+ }
+ }
+</style>
--
Gitblit v1.9.3