使用Vue3写一个抽屉Drawer组件

news/2024/7/21 14:09:38 标签: 前端, javascript, 开发语言, vue3, uniapp, web
webkit-tap-highlight-color: rgba(0, 0, 0, 0);">

一、创建抽屉组件的基本结构

<view class="drawer-container">
	<view class="mask-container"></view>
	<view class="content-container">
		<slot></slot>
	</view>
</view>

二、定义遮罩层、内容区域的基础样式

.drawer-container {
	position: fixed;
	top: 0rpx;
	left: 0rpx;
	right: 0rpx;
	bottom: 0rpx;
	z-index: 999;

	.mask-container {
		display: block;
		position: absolute;
		top: 0;
		left: 0;
		bottom: 0;
		right: 0;
		opacity: 0;
		background-color: rgba(15, 37, 41, 0.72);
		transition: opacity 0.3s;
	}

	.content-container {
		position: absolute;
		right: -100%;
		top: 0rpx;
		bottom: 0rpx;
		z-index: 999;
		background-color: #ffffff;
		transition: right 0.3s ease;
	}
}

三、JS逻辑控制显隐

javascript">import {
	defineProps,
	ref,
	reactive,
	defineExpose
} from 'vue'

/**
 * width:内容区域的宽度
 */
const props = defineProps({
	width: {
		type: String,
		default: '310px'
	}
})
// 抽屉显隐控制数据
const that = reactive({
	visible: false,
	showDrawer: false
})
let watchTimer = null

// 打开抽屉
const open = () => {
	if (that.visible) {
		return
	}
	change('visible', 'showDrawer', true)
}
// 关闭抽屉
const close = () => {
	if (!that.visible) {
		return
	}
	change('showDrawer', 'visible', false)

}
// 抽屉显隐变化
const change = (param1, param2, status) => {
	// 1、当抽屉关闭时:先控制showDrawer,使动画完成渲染,之后再操作visible关闭抽屉组件
	// 2、当抽屉开启时:先控制visible开启抽屉组件,使抽屉组件渲染,再操作showDrawer,使动画完成渲染
	that[param1] = status
	if (watchTimer) {
		clearTimeout(watchTimer)
	}
	watchTimer = setTimeout(() => {
		that[param2] = status
	}, status ? 50 : 300) // 这里的300是动画过渡时间(transition);50没有实际意义
}
// 暴露关闭、开启方法
defineExpose({
	open,
	close
})

四、visible控制组件显隐,showDrawer字段动态控制样式

<view v-if="that.visible" class="drawer-container">
	<!-- 点击遮罩关闭抽屉 -->
	<view class="mask-container" :class="{'mask-visible': that.showDrawer}" @tap="close"></view>
	<!-- 内容展示区域 -->
	<view :style="{width}" class="content-container" :class="{'content-visible--right': that.showDrawer}">
		<slot></slot>
	</view>
</view>

五、添加过渡样式

.content-visible--right {
	right: 0;
}

.mask-visible {
	display: block;
	opacity: 1;
}

六、查看完整代码

javascript"><template>
	<view v-if="that.visible" class="drawer-container">
		<!-- 点击遮罩关闭抽屉 -->
		<view class="mask-container" :class="{'mask-visible': that.showDrawer}" @tap="close"></view>
		<!-- 内容展示区域 -->
		<view :style="{width}" class="content-container" :class="{'content-visible--right': that.showDrawer}">
			<slot></slot>
		</view>
	</view>
</template>

<script setup>
import {
	defineProps,
	ref,
	reactive,
	defineExpose
} from 'vue'

/**
 * width:内容区域的宽度
 */
const props = defineProps({
	width: {
		type: String,
		default: '310px'
	}
})
// 抽屉显隐控制数据
const that = reactive({
	visible: false,
	showDrawer: false
})
let watchTimer = null

// 打开抽屉
const open = () => {
	if (that.visible) {
		return
	}
	change('visible', 'showDrawer', true)
}
// 关闭抽屉
const close = () => {
	if (!that.visible) {
		return
	}
	change('showDrawer', 'visible', false)

}
// 抽屉显隐变化
const change = (param1, param2, status) => {
	// 1、当抽屉关闭时:先控制showDrawer,使动画完成渲染,之后再操作visible关闭抽屉组件
	// 2、当抽屉开启时:先控制visible开启抽屉组件,使抽屉组件渲染,再操作showDrawer,使动画完成渲染
	that[param1] = status
	if (watchTimer) {
		clearTimeout(watchTimer)
	}
	watchTimer = setTimeout(() => {
		that[param2] = status
	}, status ? 50 : 300) // 这里的300是动画过渡时间(transition);50没有实际意义
}
// 暴露关闭、开启方法
defineExpose({
	open,
	close
})
</script>

<style lang="scss" scoped>
	.drawer-container {
		position: fixed;
		top: 0rpx;
		left: 0rpx;
		right: 0rpx;
		bottom: 0rpx;
		z-index: 999;

		.mask-container {
			display: block;
			position: absolute;
			top: 0;
			left: 0;
			bottom: 0;
			right: 0;
			opacity: 0;
			background-color: rgba(15, 37, 41, 0.72);
			transition: opacity 0.3s;
		}
	
		.content-container {
			position: absolute;
			right: -100%;
			top: 0rpx;
			bottom: 0rpx;
			z-index: 999;
			background-color: #ffffff;
			transition: right 0.3s ease;
		}
		.content-visible--right {
			right: 0;
		}

		.mask-visible {
			display: block;
			opacity: 1;
		}
	}
</style>

http://www.niftyadmin.cn/n/5425897.html

相关文章

RPC基础知识回顾

RPC基础知识回顾 1、先认识一下大家熟悉的HTTP 大家都了解HTTP吧。相信项目中也用过一些。 比如: JDK自带的老旧的HttpURLConnection&#xff0c;封装写的很累,java8之前基于HTTP1.0。在java9开始支持Http2.0Spring的其中RestTemplate都是基于HTTP/1.1的请求。最新的还有Sp…

sql设置插入之前进行判断,是否数据重复,出现过则不添加

在SQL中&#xff0c;可以使用INSERT IGNORE语句来实现在插入数据之前进行判断&#xff0c;如果数据已经存在则不会添加。 假设有以下表结构&#xff1a; CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50) NOT NULL,email VARCHAR(100) NOT NULL UNIQ…

蓝桥杯练习系统(算法训练)ALGO-975 P0802字符串表达式

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 编写一个字符串表达式求解函数int expression(char* s); 输入一个字符串表达式&#xff0c;返回它的结果。表达式长度不会超过100。表…

功能测试--APP专项测试

功能测试--APP专项测试 兼容性--云测平台模拟器兼容性怎么做安装卸载升级干扰测试推送规则--push推送服务器(是否按照规则去推送)手机端 用户体验 兼容性–云测平台模拟器 手机型号不同品牌商,不同机型(华为P30)操作系统版本:分辨率屏幕 1.尺寸:5.1. 5.5 4.7 2.类型: 刘海屏 水…

JDK8 stream toMap方法介绍

JDK8 List转Map方法&#xff0c;有下3种方法。 toMap(keyMapper, valueMapper); toMap(keyMapper, valueMapper, BinaryOperator<U> mergeFunction); toMap(keyMapper, valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);keyMapper&a…

2024-3-13-C++day3作业

1.思维导图 2. 要求&#xff1a; 设计一个Per类&#xff0c;类中包含私有成员:姓名、年龄、指针成员身高、体重&#xff0c;再设计一个Stu类&#xff0c;类中包含私有成员:成绩、Per类对象p1&#xff0c;设计这两个类的构造函数、析构函数和拷贝构造函数。 源代码&#xff1…

C++提高笔记(二)---STL容器(初识、string)

1、STL初识 1.1STL的诞生 • 长久以来&#xff0c;软件界一直希望建立一种可重复利用的东西 •C的面向对象和泛型编程思想&#xff0c;目的就是复用性的提升 • 大多情况下&#xff0c;数据结构和算法都未能有一套标准&#xff0c;导致被迫从事大量重复工作 • 为了建立数据结…

Python进阶学习(3)绑定方法

文章目录 一、绑定方法1.类方法 &#xff08;绑定&#xff09;2.主要用途包括3.静态方法&#xff08;非绑定&#xff09;4.主要用途包括5.检查类型 一、绑定方法 1.类方法 &#xff08;绑定&#xff09; 通过装饰器classmethod 进行装饰&#xff0c;绑定类cls 类方法操作一定…