Browse Source

custom-tabs组件

zyj 1 year ago
parent
commit
279a7d4337

+ 22 - 0
uni_modules/custom-tabs/changelog.md

@@ -0,0 +1,22 @@
+## 1.0.8(2022-04-21)
+1. 优化插件,避免多个组件互相影响。
+## 1.0.7(2022-04-20)
+1. 优化
+## 1.0.6(2022-04-20)
+1. 修改使用多个该组件存在的BUG
+## 1.0.5(2022-03-24)
+1. 修复设置animation参数无效的BUG
+2. 修复有动画切换的显示BUG
+## 1.0.4(2022-03-08)
+1. 增加defaultTextStyle字段,方便直接配置未选中的tab样式
+2. 增加activeTextStyle字段,方便直接配置选中后tab的样式
+3. 增加activeLineStyle字段,方便直接配置选中后下划线的样式
+## 1.0.3(2022-03-07)
+1. 修改vue2模式下 tablist is not defined 报错的bug
+## 1.0.2(2022-03-02)
+1. 新增tabs切换那一栏固定功能,类似吸顶效果
+2. 新增监听label变化,label值可动态改变
+3. 新增不显示的页面进行隐藏,防止某页面内容过多撑开其他页面
+4. h5隐藏滚动条
+## 1.0.0(2021-12-13)
+1.0.0

+ 72 - 0
uni_modules/custom-tabs/components/custom-tab-pane/custom-tab-pane.vue

@@ -0,0 +1,72 @@
+<template>
+	<view class="tab-pane">
+		<template v-if="show">
+			<slot></slot>
+		</template>
+		<template v-else>
+			<view style="width: 750rpx;height: 0;"></view>
+		</template>
+	</view>
+</template>
+<script setup>
+	// // #ifdef VUE3
+	// import { ref, watch } from 'vue';
+	// const data_props = defineProps({
+	// 	label: [String, Number],
+	// 	name: [String, Number]
+	// });
+	// const show = ref(false);
+	// let timer = 0;
+	// const watchTabKey = `watchTabValue_${data_props.name.split('_')[0]}`;
+	// console.log(watchTabKey)
+	// watch(() => data_props.label, (newValue, oldValue) => {
+	// 	uni.$emit(watchTabKey, { newValue: newValue, oldValue: oldValue, name: data_props.name });
+	// }, { immediate: true });
+	// uni.$on('putChange', item => {
+	// 	if (timer) clearTimeout(timer);
+	// 	show.value = true;
+	// 	timer = setTimeout(() => {
+	// 		show.value = data_props.name == item.name;
+	// 	}, item.duration)
+	// })
+	// // #endif
+</script>
+<script>
+	export default {
+		props: ['label', 'name'],
+		data() {
+			return {
+				timer: 0,
+				show: false,
+				watchTabKey: `watchTabValue_${this.name.split('_')[0]}`,
+				putChangeKey: `putChange_${this.name.split('_')[0]}`
+			}
+		},
+		created() {
+			uni.$on(this.putChangeKey, item => {
+				if (this.timer) clearTimeout(this.timer);
+				this.show = true;
+				this.timer = setTimeout(() => {
+					this.show = this.name == item.name;
+				}, item.duration)
+			})
+		},
+		watch: {
+			label: {
+				deep: true,
+				handler(newValue, oldValue) {
+					uni.$emit(this.watchTabKey, { newValue: newValue, oldValue: oldValue, name: this.name });
+				},
+				immediate: true
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.tab-pane {
+		width: 750rpx;
+		// #ifndef APP-PLUS-NVUE
+		flex-shrink: 0;
+		// #endif
+	}
+</style>

+ 221 - 0
uni_modules/custom-tabs/components/custom-tabs/custom-tabs.vue

@@ -0,0 +1,221 @@
+<template>
+	<view :class="['tab',{'tab-fixed':fixed}]">
+		<scroll-view :class="['tab-bar',{'tab-bar-center':tabCenter}]" scroll-x="true" :scroll-into-view="scrollId" scroll-with-animation>
+			<view v-for="(item,index) in tabList" class="tab-bar-item" :class="{'active':tabIndex==index}" :id="`tab_${index}`" :style="[{'padding':`0 ${tabSpacing}rpx`},tabIndex==index?activeTextStyle:defaultTextStyle]" :key="index" @click="putChange(item.name,index);tabChange(index)">
+				<text class="txt">{{item.label}}</text>
+				<text class="active-line" v-if="tabIndex==index" :style="[activeLineStyle]"></text>
+			</view>
+		</scroll-view>
+		<view class="tab-cont" :style="{'transform':`translateX(${translateX}%)`,'transition':`transform ${d/1000}s ease-in-out`}">
+			<slot></slot>
+		</view>
+	</view>
+</template>
+<script>
+	export default {
+		name: "tabs",
+		props: {
+			type: {
+				type: [String],
+				default: ''
+			},
+			value: { // 默认选中项
+				type: [Number, String],
+				default: 0
+			},
+			tabSpacing: { // tabbar的间距
+				type: [Number, String],
+				default: 20
+			},
+			animation: { // 切换动画
+				type: Boolean,
+				default: true
+			},
+			duration: { // 滑动动画时长 单位毫秒
+				type: [Number, String],
+				default: 200
+			},
+			tabCenter: { // tabbar是否居中
+				type: Boolean,
+				default: false
+			},
+			fixed: { // 该组件是否固定位置
+				type: Boolean,
+				default: false
+			},
+			defaultTextStyle: { // 未选中文字的样式
+				type: [Object]
+			},
+			activeTextStyle: { // 选中后文字的样式
+				type: [Object]
+			},
+			activeLineStyle: { // 选中下划线的样式
+				type: [Object]
+			}
+		},
+		data() {
+			return {
+				tabList: [],
+				tabIndex: 0,
+				d: this.duration,
+				translateX: 0,
+				scrollId: 'tab_0',
+				top: 0,
+				timer: 0,
+				timer2: 0,
+				watchTabValueKey: `watchTabValue_${this.type}`,
+				putChangeKey: `putChange_${this.type}`
+			}
+		},
+		created() {
+			uni.$off(this.watchTabValueKey);
+			uni.$on(this.watchTabValueKey, o => {
+				if (o.name.split('_')[0] != this.type) return false;
+				if (typeof o.oldValue == 'undefined') {
+					this.tabList.push({
+						label: o.newValue,
+						name: o.name
+					});
+					if (this.timer) clearTimeout(this.timer);
+					this.timer = setTimeout(() => {
+						if (this.tabList[this.value]) this.putChange(this.tabList[this.value].name);
+					}, 5)
+				} else this.tabList.forEach(item => {
+					if (item.label == o.oldValue && item.name == o.name) item.label = o.newValue;
+				})
+			})
+		},
+		watch: {
+			value: {
+				handler(val) {
+					this.tabChange(val);
+				},
+				immediate: true
+			},
+			animation: {
+				handler(val) {
+					if (!val) this.d = 0;
+				},
+				immediate: true
+			}
+		},
+		methods: {
+			tabChange(index) {
+				if (this.tabIndex == index) return false;
+				this.tabIndex = index;
+				this.translateX = -100 * index;
+				this.$nextTick(() => {
+					this.scrollId = `tab_${index-1}`;
+				})
+				if (this.timer2) clearTimeout(this.timer2);
+				this.timer2 = setTimeout(() => {
+					if (this.tabList[index]) this.$emit('change', {
+						value: index,
+						...this.tabList[index]
+					});
+				}, 20)
+			},
+			putChange(name, index) {
+				if (this.tabIndex == index) return false;
+				uni.$emit(this.putChangeKey, {
+					name: name,
+					duration: this.d,
+					type: index > this.tabIndex ? 1 : 2
+				});
+			}
+		}
+	}
+</script>
+<style>
+	/* #ifndef APP-PLUS-NVUE */
+	>>> ::-webkit-scrollbar {
+		display: none;
+		width: 0 !important;
+		height: 0 !important;
+		-webkit-appearance: none;
+		background: transparent;
+		color: transparent;
+	}
+
+	/* #endif */
+	.tab-bar.tab-bar-center {
+		text-align: center;
+	}
+</style>
+<style scoped lang="scss">
+	.tab {
+		// #ifndef APP-PLUS-NVUE
+		display: flex;
+		flex-direction: column;
+		overflow-x: hidden;
+
+		// #endif
+		.tab-bar {
+			position: relative;
+			height: 90rpx;
+			// #ifndef APP-PLUS-NVUE
+			white-space: nowrap;
+			// #endif
+			background-color: #fff;
+
+			// #ifndef APP-PLUS-NVUE
+			&::after {
+				content: '';
+				width: 100%;
+				height: 2rpx;
+				position: absolute;
+				bottom: 0;
+				left: 0;
+				background: #ccc;
+			}
+
+			// #endif
+			&-item {
+				// #ifndef APP-PLUS-NVUE
+				display: inline-block;
+				// #endif
+				height: 90rpx;
+				line-height: 90rpx;
+				font-size: 30rpx;
+				color: #222;
+				text-align: center;
+
+				&.active {
+					position: relative;
+					color: #007AFF;
+				}
+
+				// #ifndef APP-PLUS-NVUE
+				.active-line {
+					position: absolute;
+					bottom: 2rpx;
+					left: 50%;
+					transform: translateX(-50%);
+					width: 80rpx;
+					height: 2rpx;
+					background: #007AFF;
+				}
+
+				// #endif
+			}
+		}
+
+		&-fixed {
+			height: 100vh;
+
+			.tab-bar {
+				position: sticky;
+				top: 0px;
+				z-index: 2022;
+			}
+		}
+
+		.tab-cont {
+			// #ifndef APP-PLUS-NVUE
+			display: flex;
+			// #endif
+			flex-direction: row;
+			padding: 20rpx 0;
+		}
+	}
+</style>

+ 83 - 0
uni_modules/custom-tabs/package.json

@@ -0,0 +1,83 @@
+{
+  "id": "custom-tabs",
+  "displayName": "Tabs标签页 灵活配置 多端兼容(暂停维护谨慎使用,建议使用uv-tabs)",
+  "version": "1.0.8",
+  "description": "在做项目的过程中用到了tab切换,本想着去插件市场找一个直接现用,后面发现找到的tab切换并不是我想要的那种使用方式,于是我结合了element-ui中Tabs标签页的方式写了该组件...",
+  "keywords": [
+    "tabs",
+    "tab",
+    "tabs标签页",
+    "tab切换",
+    "标签页"
+],
+  "repository": "https://gitee.com/my_dear_li_pan/my-uni-modules.git",
+"engines": {
+  },
+  "dcloudext": {
+    "category": [
+        "前端组件",
+        "通用组件"
+    ],
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "y"
+        },
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "u",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "n",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        }
+      }
+    }
+  }
+}

+ 149 - 0
uni_modules/custom-tabs/readme.md

@@ -0,0 +1,149 @@
+- <a href="#c1" title="概要">概要</a>
+- <a href="#c2" title="Tips">Tips</a>
+- <a href="#c3" title="支持的平台">支持的平台</a>
+- <a href="#c4" title="使用示例">使用示例</a>
+- <a href="#c5" title="Tabs Attributes">Tabs Attributes</a>
+- <a href="#c6" title="Tabs Events">Tabs Events</a>
+- <a href="#c7" title="Tab-pane Attributes">Tab-pane Attributes</a>
+- <a href="#c8" title="关注我,不迷路">关注我,不迷路</a>
+
+<div id="c1"></div>
+
+#### 概要
+
+在做项目的过程中用到了tab切换,本想着去插件市场找一个直接现用,后面发现找到的tab切换并不是我想要的那种使用方式,于是我结合了element-ui中Tabs标签页的方式写了该组件。
+
+
+<div id="c2"></div>
+
+#### Tips
+
+1. 该插件使用的预编译,需要自行安装scss/sass插件。
+2. 该插件同时兼容了VUE2和VUE3,hbuilderX 最好是更新到较新版本。
+3. 由于组件重构升级,老用户需要更新插件的,需要注意参数,根据下面提供的参数修改即可。
+4. 遵循uni_modules规范插件。
+5. 如果发现组件有bug或者不完善可以留言交流。
+6. uniapp插件git地址:https://gitee.com/my_dear_li_pan/my-uni-modules.git
+7. 个人博客地址:https://blog.csdn.net/qq_42961150?spm=1011.2124.3001.5343
+
+<div id="c3"></div>
+
+#### 支持的平台
+- H5、app-vue、微信小程序、百度小程序等小程序平台。
+- 暂不支持nvue。
+- cli脚手架项目是否可用,暂未测试。
+
+<div id="c4"></div>
+
+#### 使用示例
+```
+<template>
+	<view>
+		<custom-tabs type="c1" :value="value" @change="changeIndex">
+			<custom-tab-pane label="标签一" name="c1_1">
+				<view style="height: 100px;">内容0</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+				<view style="height: 100px;">内容1</view>
+			</custom-tab-pane>
+			<custom-tab-pane label="标签二" name="c1_2">内容2</custom-tab-pane>
+			<custom-tab-pane label="标签三3" name="c1_3">内容3</custom-tab-pane>
+			<custom-tab-pane label="标签四44" name="c1_4">内容4</custom-tab-pane>
+			<custom-tab-pane label="标签五555" name="c1_5">内容5</custom-tab-pane>
+			<custom-tab-pane label="标签六6666" name="c1_6">内容6</custom-tab-pane>
+			<custom-tab-pane label="标签七77777" name="c1_7">内容7</custom-tab-pane>
+		</custom-tabs>
+	</view>
+</template>
+<script setup>
+    // #ifdef VUE3
+	import { reactive, ref, watch } from 'vue';
+	const value = ref(2);
+
+	function changeIndex(e) {
+		console.log('选中:', e)
+	}
+	// #endif
+</script>
+<script>
+	// #ifdef VUE2
+	export default {
+		data() {
+			return {
+				value: 2
+			}
+		},
+		methods: {
+			changeIndex(e) {
+				console.log('选中:', e)
+			}
+		}
+	}
+	// #endif
+</script>
+```
+
+<div id="c5"></div>
+
+#### Tabs Attributes
+
+参数|说明|类型|是否必填|可选值|默认值
+-|-|-|-|-|-|
+type|组件的唯一标识,如果有多个该组件,则值必须不同|string|是|-|-
+value|选中选项的索引,从0开始|Number|否|-|0
+animation|切换动画|Boolean|否|true/false|true
+duration|切换动画的动画时长,单位ms|Number|否|-|200
+tabSpacing|tab选项的左右间距,单位rpx|Number|否|-|40
+tabCenter|tab选项是否居中显示|Boolean|否|true/false|false
+fixed|tab选项固定|Boolean|否|true/false|false
+defaultTextStyle|未选中tab选项的样式|Object|否|示例:```:defaultTextStyle="{color:'pink'}"```|-
+activeTextStyle|选中后tab选项的样式|Object|否|示例:```:activeTextStyle="{color:'red','font-weight':700}"```|-
+activeLineStyle|选中后tab选项下划线的样式|Object|否|示例:```:activeLineStyle="{'background-color':'red',height:'6rpx'}"```|-
+
+<div id="c6"></div>
+
+#### Tabs Events
+事件名称|说明|回调参数
+-|-|-|
+change|tab 被选中时触发|被选中的标签tab实例
+
+<div id="c7"></div>
+
+#### Tab-pane Attributes
+
+参数|说明|类型|是否必填|可选值|默认值
+-|-|-|-|-|-|
+label|选项卡标题|String|是|-|-
+name|与选项卡绑定值 value 对应的标识符,表示选项卡别名。==注意:== 该值的格式必须和组件上的type配合使用,eg:type="c1",name="c1_"+自定义值|String|是|-|该选项卡在选项卡列表中的顺序值,如第一个选项卡则为'c1_1'
+
+<div id="c8"></div>
+
+**----- 别忘记点赞哟,您的肯定就是对我最大的支持 END -----**
+
+#### 关注我,不迷路
+
+如果任何疑问的可以在评论区留言,还可以加QQ群交流:568984539,加群备注‘地区-名字-技术类型’。
+
+更多前端等相关知识可关注我个人博客:https://blog.csdn.net/qq_42961150?spm=1011.2124.3001.5343
+
+**个人作品展示:**
+
+uniapp+vue3.2+unicloud开发微信小程序:**皮皮虎去水印**。
+
+关注下方公众号:【**全网免费网盘资源**】、【**美团外卖饿了么天天领红包**】、【**去水印**】。
+
+![image](https://vkceyugu.cdn.bspapp.com/VKCEYUGU-bb657efd-fece-483e-a715-5daea480fde8/6e029310-aec8-46e9-9883-1c88dc1925ad.jpg)
+
+
+
+
+
+
+
+