使用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>
相关推荐
Code Warrior39 分钟前
【每日算法】专题五_位运算
开发语言·c++
孤水寒月3 小时前
基于HTML的悬窗可拖动记事本
前端·css·html
沐知全栈开发3 小时前
HTML DOM 访问
开发语言
祝余呀3 小时前
html初学者第一天
前端·html
脑袋大大的4 小时前
JavaScript 性能优化实战:减少 DOM 操作引发的重排与重绘
开发语言·javascript·性能优化
二进制person5 小时前
Java SE--方法的使用
java·开发语言·算法
速易达网络5 小时前
RuoYi、Vue CLI 和 uni-app 结合构建跨端全家桶方案
javascript·vue.js·低代码
OneQ6665 小时前
C++讲解---创建日期类
开发语言·c++·算法
耶啵奶膘5 小时前
uniapp+firstUI——上传视频组件fui-upload-video
前端·javascript·uni-app
JoJo_Way5 小时前
LeetCode三数之和-js题解
javascript·算法·leetcode