uniapp插件-导航栏菜单设计与实现(实现)

「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战」。

前言

上一篇我们说到了整体的构思和参数考量,我们就来看看具体的实现吧!
通过本章我们可以学习到:
1、flex布局。
2、createSelectorQuery()应用。

DOM

很简单没啥说的,主要就是下面。
1、主要分为scroll滑动和不滑动两种。
2、通过<slot>暴露后备内容
3、<view class="link-p" :style="{ width: w i d t h u p x , b a c k g r o u n d : c o l o u r , l e f t : {width}upx`, background: colour, left: ` {LeftPx}px, transition: left ${sec}s ease-in-out }"></view>这段主要是我们胶囊滑动的实现。很简单通过:transition实现。坐标移动目前采用最简单的left。看代码:

<template>
	<view>
		<view class="scroll-view-x" v-if="scroll">
			<view :id="'the-' + index" v-for="(item, index) in option" :key="item.id" class="scroll-view-item " @tap="calculator(index)">
				<slot name="scroll" :item="item" :active="idx == index">
					<!-- 后备内容 -->
					{{ item.name }}
				</slot>
			</view>
			<view class="link-p" :style="{ width: `${width}upx`, background: colour, left: `${LeftPx}px`, transition: `left ${sec}s ease-in-out` }"></view>
		</view>
		<view class="scroll-view-x no-scroll" v-else>
			<view :id="'the-' + index" v-for="(item, index) in option" :key="item.id" class="scroll-view-item " @tap="calculator(index)">
				<slot :item="item" :active="idx == index">
					<!-- 后备内容 -->
					{{ item.name }}
				</slot>
			</view>
			<view class="link-p" :style="{ width: `${width}upx`, background: colour, left: `${LeftPx}px`, transition: `left ${sec}s ease-in-out` }"></view>
		</view>
	</view>
</template>
复制代码

css

这部分最重要的就是felx布局中的justify-content: space-between;属性的使用。通过它可以做到内容的自动适应。对flex还不了解我们可以查看Flex 布局语法教程,有图有说明很清楚。好了看代码:

<style scoped>
.scroll-view-x {
	display: flex;
	flex-direction: row;
	height: 88upx;
	white-space: nowrap;
	width: 100%;
	background-color: #ffffff;
	box-sizing: border-box;
	position: relative;
	justify-content: space-between;
	overflow: auto;
}
.no-scroll{
	overflow: hidden;
}
.scroll-view-x .scroll-view-item {
	display: inline-block;
	text-align: center;
	font-size: 30upx;
	padding: 0 25upx;
	color: #787878;
	height: 88upx;
	line-height: 88upx;
}
.scroll-view-x .tapitem {
	color: #ff8c39;
	position: relative;
}
.scroll-view-x .link-p {
	position: absolute;
	height: 5upx;
	border-radius: 4upx;
	bottom: 10upx;
	transition: left 0.25s ease-in-out;
	width: 40upx;
	background: rgba(243, 152, 0, 1);
}
.scroll-view-x .link-p .link {
	display: block;
	margin: 0 auto;
	height: inherit;
	border-radius: 4px;
}
</style>
复制代码

script部分

这部分分为两点:
1、props的确定,昨天我们设计的时候已经说了,确定好类型就行。
2、因为我们的内容是不确定的也是不等宽的,所以我们要获取到节点的位置信息。我们这边使用uni.createSelectorQuery()。还不了解我们查看链接。通过boundingClientRect(callback)可以得到节点位置信息。我们保存起来就可以了。
note:注意第二步节点获取要在this.$nextTick中。
3、通过点击选项的事件,我们改变胶囊LeftPx参数值就大功告成了,其实挺简单的。
看代码:

export default {
	name: 'duNav',
	props: {
		/**
		 * 是否滑动
		 */
		scroll: {
			type: Boolean,
			default: true
		},
		/**
		 * 样式类型
		 */
		classType: {
			type: [Number],
			default: 0
		},
		/**
		 * 胶囊速度
		 */
		sec: {
			type: [Number, String],
			default: 0.25
		},
		/**
		 * 胶囊宽
		 */
		width: {
			type: [Number, String],
			default: 40
		},
		/**
		 * 胶囊颜色
		 */
		colour: {
			type: String,
			default: 'rgba(243, 152, 0, 1)'
		},
		/**
		 * 选项
		 */
		option: {
			type: [Array],
			default: () => [{ name: '全部' }]
		}
	},
	data() {
		return {
			idx: 0,
			LeftPx: 0
		};
	},
	created() {
		this.initialPra();
	},
	methods: {
		initialPra() {
			this.$nextTick(() => {
				for (let i in this.option) {
					const query = uni.createSelectorQuery().in(this);
					query
						.select('#the-' + i)
						.boundingClientRect(data => {
							let { left, width } = data;
							this.option[i].left = left;
							this.option[i].width = data.width;
							if (Number(i) === 0) {
								this.LeftPx = this.option[0].width / 2 - this.width / 4;
							}
						})
						.exec();
				}
			});
		},
		calculator(i) {
			let initial = this.option[0].left;
			let left = this.option[i].left;
			let width = this.option[i].width;
			this.idx = i;
			this.LeftPx = left + width / 2 - this.width / 4 - initial;
			this.$emit('feedback', i);
		}
	}
};
</script>
复制代码

结尾

至此,一个完整的导航栏菜单就实现了。代码下载戳链接!
如果你也想自己开发插件方便自己和他人使用可以查看教程!

猜你喜欢

转载自juejin.im/post/7035268969103622152