使用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>
相关推荐
We་ct30 分钟前
深度剖析浏览器跨域问题
开发语言·前端·浏览器·跨域·cors·同源·浏览器跨域
skywalk816338 分钟前
在考虑双轨制,即在中文语法的基础上,加上数学公式的支持,这样像很多计算将更加简单方便,就像现在的小学数学课本里面一样,比如:定x=2*x + 1
开发语言
小书房41 分钟前
Kotlin的by
android·开发语言·kotlin·委托·by
weixin_427771611 小时前
前端调试隐藏元素
前端
就叫飞六吧1 小时前
QT写一个桌面程序exe并动态打包基本流程(c++)
开发语言·c++
threelab1 小时前
Three.js 代码云效果 | 三维可视化 / AI 提示词
开发语言·javascript·人工智能
V搜xhliang02461 小时前
OpenClaw科研全场景用法:从文献到实验室的完整自动化方案
运维·开发语言·人工智能·python·算法·microsoft·自动化
kaikaile19951 小时前
风、浪、流环境模型的船舶三自由度(纵荡、横荡、艏摇)运动仿真MATLAB
开发语言·人工智能·matlab
fish_xk1 小时前
map和set
java·开发语言
李崧正2 小时前
Java技术分享:Lambda表达式与函数式编程
java·开发语言·python