uni 导航栏超出部分隐藏,点击导航栏,导航栏位置也进行向前移动

 1.组件部分

<template>
	<view :id="'tab'+id">
		<scroll-view class="scroll-view_H" scroll-x="true" :scroll-left="scrollLeft">
			<view :id="'tab-item'+index" :class="['scroll-view-item',current==index?'active':'']" :style="[tabItemStyle(index)]" v-for="(item,index) in list" @click="itemClick(item,index)">
				<view class="flex-display flex-column a-i-c">
					<image class="u-icon__img" :src="item.img" mode="widthFix"></image>
					<view class="flex-display fs24 a-i-c j-c-c mar-top-20 fs-bold" :class="[current==index?'active-check':'']">{{item.name}}</view>
				</view>
			</view>
		</scroll-view>
	</view>
</template>

<script>
	function guid(len = 32, firstU = true, radix = null) {
		let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
		let uuid = [];
		radix = radix || chars.length;

		if (len) {
			// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
			for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
		} else {
			let r;
			// rfc4122标准要求返回的uuid中,某些位为固定的字符
			uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
			uuid[14] = '4';

			for (let i = 0; i < 36; i++) {
				if (!uuid[i]) {
					r = 0 | Math.random() * 16;
					uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
				}
			}
		}
		// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
		if (firstU) {
			uuid.shift();
			return 'u' + uuid.join('');
		} else {
			return uuid.join('');
		}
	}
	export default {
		props: {
			current: { //当前选中的tab
				type: [Number, String],
				default: 0
			},
			list: { //tab列表数据
				type: Array,
				default () {
					return []
				}
			},
			barStyle: { //自定义底部横条样式
				type: Object,
				default () {
					return {}
				}
			},
			itemStyle: { //自定义选中项tab的样式
				type: Object,
				default () {
					return {}
				}
			},
			activeColor: { //tab选中字体颜色
				type: String,
				default: 'rgb(41, 121, 255)'
			},
			inactiveColor: { //tab未选中字体颜色
				type: String,
				default: 'rgb(48, 49, 51)'
			},
			showBar: { //是否显示底部的横条
				type: Boolean,
				default: true
			},
			// 用于显示图片小图标时,图片的宽度
			iconWidth: {
				type: [String, Number],
				default: ''
			},
			// 用于显示图片小图标时,图片的高度
			iconHeight: {
				type: [String, Number],
				default: ''
			},
			// 字体大小单位rpx
			fontSize: {
				type: [String, Number],
				default: 30
			}
		},
		data() {
			return {
				scrollLeft: 0,
				animation: '',
				id: guid(10),
				parentLeft: '',
				componentWidth: '',
				tabQueryInfo: []
			};
		},
		watch: {
			current() {
				setTimeout(() => {
					this.animation = ''
				}, 500)
				this.scrollByIndex()
			}
		},
		computed: {
			tabItemStyle() {
				return (index) => {
					let style = {
						fontSize: this.addUnit(this.fontSize)
					}
					if (index == this.current) {
						style.color = this.activeColor
						Object.assign(style, this.itemStyle);
					} else {
						style.color = this.inactiveColor
					}
					return style
				}
			},
			isImg() {
				return (name) => {
					if (typeof name == 'undefined' || !name) {
						return false
					}
					return name.indexOf('/') !== -1;
				}

			},
			imgStyle() {
				let style = {};
				// 如果设置width和height属性,则优先使用,否则使用size属性
				style.width = this.iconWidth ? this.addUnit(this.width) : this.addUnit(this.fontSize);
				style.height = this.iconHeight ? this.addUnit(this.height) : this.addUnit(this.fontSize);
				return style;
			}
		},
		mounted() {
			this.init()
		},
		methods: {
			// 设置一个init方法,方便多处调用
			init() {
				// 获取tabs组件的尺寸信息
				uni.createSelectorQuery().
				in(this)['select']('#tab' + this.id)
					.boundingClientRect(tabRect => {
						// tabs组件距离屏幕左边的宽度
						this.parentLeft = tabRect.left;
						// tabs组件的宽度
						this.componentWidth = tabRect.width;
						this.getTabRect();
					})
					.exec()
			},
			// 查询tab的布局信息
			getTabRect() {
				// 创建节点查询
				let query = uni.createSelectorQuery().in(this);
				// 历遍所有tab,这里是执行了查询,最终使用exec()会一次性返回查询的数组结果
				for (let i = 0; i < this.list.length; i++) {
					// 只要size和rect两个参数
					// 只要size和rect两个参数
					query.select(`#tab-item${i}`).fields({
						size: true,
						rect: true
					});
				}
				// 执行查询,一次性获取多个结果
				query.exec(
					function(res) {
						this.tabQueryInfo = res;
						// 初始化滚动条和移动bar的位置
						this.scrollByIndex();
					}.bind(this)
				);
			},
			// 滚动scroll-view,让活动的tab处于屏幕的中间位置
			scrollByIndex() {
				// 当前活动tab的布局信息,有tab菜单的width和left(为元素左边界到父元素左边界的距离)等信息
				let tabInfo = this.tabQueryInfo[this.current];
				if (!tabInfo) return;
				// 活动tab的宽度
				let tabWidth = tabInfo.width;
				// 活动item的左边到tabs组件左边的距离,用item的left减去tabs的left
				let offsetLeft = tabInfo.left - this.parentLeft;
				// 将活动的tabs-item移动到屏幕正中间,实际上是对scroll-view的移动
				let scrollLeft = offsetLeft - (this.componentWidth - tabWidth) / 2;
				this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft;
			},
			addUnit(value = 'auto', unit = 'rpx') {
				value = String(value);
				// 用uView内置验证规则中的number判断是否为数值
				return /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value) ? `${value}${unit}` : value;
			},
			itemClick(item, index) {
				this.$emit('click', index)
				if (this.current == index) return
				if (this.current > index) {
					this.animation = 'animate__animated animate__slideInRight'
				} else {
					this.animation = 'animate__animated animate__slideInLeft'
				}
				this.$emit('change', index)

			}
		}
	}

</script>

<style lang="scss">
	.active-check{
		width: 134upx;
		height: 43upx;
		font-family: PingFang SC;
		color: #FFFFFF;
		background: #FCAC39;
		border-radius: 22px;
	}
	.scroll-view_H {
		white-space: nowrap;
	}

	.scroll-view-item {
		width: 150upx;
		display: inline-block;
		padding: 20rpx 0rpx;
		transition: all 0.2s ease;
	}

	.active {
		position: relative;

		.bar {
			position: absolute;
			left: 0;
			bottom: 0;
			right: 0;
			width: 40%;
			margin: 0 auto;
			height: 4rpx;
			background: #007AFF;
			animation-duration: 0.1s;
		}
	}

	.u-icon__img {
		width: 88upx;
		height: 88upx;
	}
</style>

引用组件

<template>
	<view style="height:101vh;" class=" flex-display flex-column">
		
		
			<nav-tab :list="list1" :current="current" :showBar="true" :fontSize="30" @click="tabClick" @change="change">
			</nav-tab>
		</view>

		

	</view>
</template>

<script>

	import navTab from '../../components/goods-public/nav-tabs.vue'
	
	export default {
		components: {
		
			navTab,
		
		},
		data() {
			return {
				current: 0,
				list1: [],
			}
		},
		mounted() {
			
		},
		
		onLoad(option) {
			
			this.navList()
			
		},
		onReachBottom(e) {
			
		},
		methods: {
			navList() {
				this.list1 = [{
								name: '全部',
								img: '../../static/img/goods/shop-all.png'
							}, {
								name: '苹果',
								img: '../../static/img/goods/sg-pg.png'
							}, {
								name: '橘子',
								img: '../../static/img/goods/sg-cz.png'
							}, {
								name: '石榴',
								img: '../../static/img/goods/sg-sl.png'
							},
							{
								name: '梨子',
								img: '../../static/img/goods/sg-l.png'
							},
							
						]
			},
			
			tabClick(index) {
				// console.log(index)
			},
			change(index) {
				this.current = index
			},
		}
	}
</script>

<style lang="scss" scoped>
	page {
		background-color: rgba(246, 244, 247, 1);
	}

	.content-c {
		display: flex;
		flex-direction: column;
		flex: 1;
		border-radius: 0rpx 0rpx 0rpx 0rpx;
	}

	.list-scroll-content {
		height: 100%;
		width: 100%;
		border-radius: 38upx 38upx 0upx 0upx;
	}

	.swiper-item {
		height: 100%;
		width: 100%;
		border-radius: 38upx 38upx 0upx 0upx;

	}

	.swiper-box {
		height: 100%;
		width: 100%;
		border-radius: 38upx 38upx 0upx 0upx;
	}
</style>

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值