uniapp低代码可视化-自定义精美选项卡-代码生成器

在UniApp中创建自定义的可自由滚动的精美选项卡组件,你可以结合UniApp的组件、样式和逻辑来实现。实现这样的效果首先选到的是scroll-view、view、 text三个组件组成,接下来我们使用工具教大家实现。

模板复用

此组件我们已经发布至组件模板,即需搜索选项卡、找到我们这个组件即可快速复用。

实现选项卡效果

FLEX组件拖动至设计区

首先找到我们的flex组件拖至设计区,开启水平滚动属性即可变成scroll-view组件。

选项卡标题设置

选项卡标题存在选中标题、非选中标题,我们使用FLEX组件装起来。定义选项卡的数据tabDatas,tabScrollLeft,tabIndex等属性

选中、非选中效果样式位置

选项卡包括一个选中、一个非选中效果。我们采用文本内容来分别设置对应的样式。

选中、非选中判断显示

选中的时候tabIndex==index

非选中的时候tabIndex!=index

点击事件切换选中

组件扩展方法增加自己的选中方法实现this.tabIndex=index

绑定点击事件

调用方法传入index

友好滚动扩展属性

为了点击对应的选项卡滚动至对应的选项卡尽量保持中间位置,使用了scroll-view里scroll-left属性。在第一步找到开启水平滚动flex组件增加扩展属性:scroll-with-animation="true" enhanced :scroll-left="tabsScrollLeft"

生成源码

生成源码即可在hbuilder实时查看效果。

<template>
	<view class="container container329152">
		<view class="flex flex-wrap diygw-col-24 flex-direction-column">
			<text class="diygw-col-24 text1-clz"> 已绑定组件动态数据,导出源码起效。组件数据在上面一层扩组数据里,可以根据动态API的数据来绑定。使用时可删除此提示 </text>
			<scroll-view scroll-x :scroll-with-animation="true" enhanced :scroll-left="tabsScrollLeft" class="flex scroll-view flex-wrap diygw-col-24 flex10-clz">
				<view class="flex flex-nowrap">
					<view v-for="(item, index) in tabDatas" :key="index" class="flex flex-wrap diygw-col-0 flex-direction-column items-center flex12-clz" @tap="selectTabs(index)">
						<text v-if="tabIndex == index" class="diygw-text-line1 diygw-col-24 gradual-red text6-clz">
							{{ item.title }}
						</text>
						<text v-if="tabIndex != index" class="diygw-text-line1 diygw-col-0 text2-clz">
							{{ item.title }}
						</text>
					</view>
				</view>
			</scroll-view>
			<scroll-view scroll-x :scroll-with-animation="true" enhanced :scroll-left="tabsScrollLeft" class="flex scroll-view flex-wrap diygw-col-24 flex5-clz">
				<view class="flex flex-nowrap">
					<view v-for="(item, index) in tabDatas" :key="index" class="flex flex-wrap diygw-col-0 flex-direction-column items-center flex6-clz" @tap="selectTabs(index)">
						<text v-if="tabIndex == index" class="diygw-text-line1 diygw-col-24 gradual-orange text7-clz">
							{{ item.title }}
						</text>
						<text v-if="tabIndex != index" class="diygw-text-line1 diygw-col-0 text8-clz">
							{{ item.title }}
						</text>
					</view>
				</view>
			</scroll-view>
			<scroll-view scroll-x :scroll-with-animation="true" enhanced :scroll-left="tabsScrollLeft" class="flex scroll-view flex-wrap diygw-col-24 flex3-clz">
				<view class="flex flex-nowrap">
					<view v-for="(item, index) in tabDatas" :key="index" class="flex flex-wrap diygw-col-0 flex-direction-column items-center flex4-clz" @tap="selectTabs(index)">
						<text v-if="tabIndex == index" class="diygw-text-line1 diygw-col-24 gradual-green text4-clz">
							{{ item.title }}
						</text>
						<text v-if="tabIndex != index" class="diygw-text-line1 diygw-col-0 text5-clz">
							{{ item.title }}
						</text>
					</view>
				</view>
			</scroll-view>
			<scroll-view scroll-x :scroll-with-animation="true" enhanced :scroll-left="tabsScrollLeft" class="flex scroll-view flex-wrap diygw-col-24 flex1-clz">
				<view class="flex flex-nowrap">
					<view v-for="(item, index) in tabDatas" :key="index" class="flex flex-wrap diygw-col-0 flex-direction-column items-center flex2-clz" @tap="selectTabs(index)">
						<text v-if="tabIndex == index" class="diygw-text-line1 diygw-col-24 gradual-blue text-clz">
							{{ item.title }}
						</text>
						<text v-if="tabIndex != index" class="diygw-text-line1 diygw-col-0 text3-clz">
							{{ item.title }}
						</text>
					</view>
				</view>
			</scroll-view>
		</view>
		<view class="clearfix"></view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				//用户全局信息
				userInfo: {},
				//页面传参
				globalOption: {},
				//自定义全局变量
				globalData: { isshow: false },
				listNum: 1,
				list: {
					rows: [
						{
							id: 0,
							title: '',
							remark: '',
							img: '',
							content: null,
							cateId: 0,
							userId: 0,
							createTime: '',
							updateTime: '',
							deleteTime: null
						}
					],
					total: 0,
					code: 0,
					msg: ''
				},
				catesNum: 1,
				cates: {
					rows: [
						{
							id: 0,
							title: '',
							remark: '',
							img: '',
							userId: 0,
							createTime: '',
							updateTime: '',
							deleteTime: null
						}
					],
					total: 0,
					code: 0,
					msg: ''
				},
				tabIndex: 0,
				tabsScrollLeft: 0,
				tabDatas: [{ title: '关注' }, { title: '精选' }, { title: '推荐' }, { title: '热门' }, { title: '热门' }, { title: '热门' }, { title: '热门' }],
			};
		},
		onShow() {
			this.setCurrentPage(this);
		},
		onLoad(option) {
			this.setCurrentPage(this);
			if (option) {
				this.setData({
					globalOption: this.getOption(option)
				});
			}

			this.init();
		},
		methods: {
			async init() {
				await this.listApi();
				await this.catesApi();
			},
			// 列表数据 API请求方法
			async listApi(param) {
				let thiz = this;
				param = param || {};

				//如果请求要重置页面,请配置点击附加参数refresh=1  增加判断如输入框回调param不是对象
				if (param.refresh || typeof param != 'object') {
					this.listNum = 1;
				}

				//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
				let http_url = '/cms/api.article/list';
				let http_data = {
					pageNum: this.listNum,
					pageSize: 10,
					title_like: param.title_like || this.title
				};
				let http_header = {};

				if (this.cates.rows.length > 0 && this.utabs > 0) {
					let row = this.cates.rows[this.utabs];
					if (row.id) {
						http_data.cateId = row.id;
					}
				}

				let list = await this.$http.post(http_url, http_data, http_header, 'json');

				let datarows = list.rows;
				if (http_data.pageNum == 1) {
					this.list = list;
				} else if (datarows) {
					let rows = this.list.rows.concat(datarows);
					list.rows = rows;
					this.list = Object.assign(this.list, list);
				}
				if (datarows && datarows.length > 0) {
					this.listNum = this.listNum + 1;
				}
				this.globalData.isshow = true;
			},
			// 分类数据 API请求方法
			async catesApi(param) {
				let thiz = this;
				param = param || {};

				//请求地址及请求数据,可以在加载前执行上面增加自己的代码逻辑
				let http_url = '/cms/api.cate/list';
				let http_data = {
					pageNum: this.catesNum,
					pageSize: 10,
					pageSize: param.pageSize || '20'
				};
				let http_header = {};

				let cates = await this.$http.post(http_url, http_data, http_header, 'json');

				cates.rows.unshift({ id: '', title: '全部' });

				this.cates = cates;
			},

			// 修改数据 自定义方法
			async editFunction(param) {
				let thiz = this;
				let index = param && (param.index || param.index == 0) ? param.index : thiz.index || '';
				this.form = JSON.parse(JSON.stringify(this.list.rows[param.index]));
				this.navigateTo({
					type: 'openmodal',
					id: 'modal'
				});
			},
			selectTabs(index) {
				this.tabIndex = index;
				//根据自己的选项卡动态调整下60大小
				let tabsScrollLeft = index * 60;
				if (index <= 2) {
					tabsScrollLeft = 0;
				}
				this.tabsScrollLeft = tabsScrollLeft;
			},
			selectTabs(index) {
				this.tabIndex = index;
				//根据自己的选项卡动态调整下60大小
				let tabsScrollLeft = index * 60;
				if (index <= 2) {
					tabsScrollLeft = 0;
				}
				this.tabsScrollLeft = tabsScrollLeft;
			},
			selectTabs(index) {
				this.tabIndex = index;
				//根据自己的选项卡动态调整下60大小
				let tabsScrollLeft = index * 60;
				if (index <= 2) {
					tabsScrollLeft = 0;
				}
				this.tabsScrollLeft = tabsScrollLeft;
			},
			selectTabs(index) {
				this.tabIndex = index;
				//根据自己的选项卡动态调整下60大小
				let tabsScrollLeft = index * 60;
				if (index <= 2) {
					tabsScrollLeft = 0;
				}
				this.tabsScrollLeft = tabsScrollLeft;
			}
		},
		onPullDownRefresh() {
			// 列表数据 API请求方法
			this.listNum = 1;
			this.listApi();

			uni.stopPullDownRefresh();
		},
		onReachBottom() {
			// 列表数据 API请求方法
			this.listApi();
		}
	};
</script>

<style lang="scss" scoped>
	.text1-clz {
		margin-left: 10rpx;
		padding-top: 10rpx;
		padding-left: 10rpx;
		width: calc(100% - 10rpx - 10rpx) !important;
		padding-bottom: 10rpx;
		margin-top: 10rpx;
		margin-bottom: 10rpx;
		margin-right: 10rpx;
		padding-right: 10rpx;
	}
	.flex10-clz {
		padding-top: 10rpx;
		padding-left: 10rpx;
		padding-bottom: 10rpx;
		padding-right: 10rpx;
	}
	.flex12-clz {
		margin-left: 0rpx;
		margin-top: 0rpx;
		margin-bottom: 0rpx;
		margin-right: 10rpx;
	}
	.text6-clz {
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		font-weight: bold;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.text2-clz {
		background-color: #f4f4f4;
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.flex5-clz {
		padding-top: 10rpx;
		padding-left: 10rpx;
		padding-bottom: 10rpx;
		padding-right: 10rpx;
	}
	.flex6-clz {
		margin-left: 0rpx;
		margin-top: 0rpx;
		margin-bottom: 0rpx;
		margin-right: 10rpx;
	}
	.text7-clz {
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		font-weight: bold;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.text8-clz {
		background-color: #f4f4f4;
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.flex3-clz {
		padding-top: 10rpx;
		padding-left: 10rpx;
		padding-bottom: 10rpx;
		padding-right: 10rpx;
	}
	.flex4-clz {
		margin-left: 0rpx;
		margin-top: 0rpx;
		margin-bottom: 0rpx;
		margin-right: 10rpx;
	}
	.text4-clz {
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		font-weight: bold;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.text5-clz {
		background-color: #f4f4f4;
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.flex1-clz {
		padding-top: 10rpx;
		padding-left: 10rpx;
		padding-bottom: 10rpx;
		padding-right: 10rpx;
	}
	.flex2-clz {
		margin-left: 0rpx;
		margin-top: 0rpx;
		margin-bottom: 0rpx;
		margin-right: 10rpx;
	}
	.text-clz {
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		font-weight: bold;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.text3-clz {
		background-color: #f4f4f4;
		padding-top: 10rpx;
		border-bottom-left-radius: 120rpx;
		overflow: hidden;
		padding-left: 30rpx;
		padding-bottom: 10rpx;
		border-top-left-radius: 120rpx;
		border-top-right-radius: 120rpx;
		border-bottom-right-radius: 120rpx;
		padding-right: 30rpx;
	}
	.container329152 {
	}
</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值