使用Vue3写一个抽屉Drawer组件

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

html 复制代码
<view class="drawer-container">
	<view class="mask-container"></view>
	<view class="content-container">
		<slot></slot>
	</view>
</view>

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

css 复制代码
.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字段动态控制样式

html 复制代码
<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>

五、添加过渡样式

css 复制代码
.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>
相关推荐
禁默3 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood10 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
学代码的小前端11 分钟前
0基础学前端-----CSS DAY9
前端·css
Code哈哈笑13 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
joan_8516 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
程序猿进阶16 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_4336184418 分钟前
shell 编程(二)
开发语言·bash·shell
charlie11451419133 分钟前
C++ STL CookBook
开发语言·c++·stl·c++20
袁袁袁袁满33 分钟前
100天精通Python(爬虫篇)——第113天:‌爬虫基础模块之urllib详细教程大全
开发语言·爬虫·python·网络爬虫·爬虫实战·urllib·urllib模块教程
还是大剑师兰特38 分钟前
什么是尾调用,使用尾调用有什么好处?
javascript·大剑师·尾调用