Vue3+Ts封装类似el-dialog的对话框组件

 

提供11个字段对dialog组件进行控制:

  • modelValue: 对话框显示隐藏控制,

  • width: 控制对话框的宽度,

  • height:控制对话框的高度,

  • top: 控制对话框个距离顶部的距离,

  • title: 控制对话框的标题,

  • appendToBody: 是否将对话框添加至body,

  • closeOnClickModal: 是否点击遮罩层关闭抽屉,

  • showConfirm: 是否显示确认按钮,

  • showCancel: 是否显示取消按钮,

  • cancelText: 取消按钮的文本,

  • confirmText: 确认按钮的文本

dialog.vue代码如下

<template>
	<teleport v-if="appendToBody" to="body">
		<transition name="dialog-fade">
			<div v-show="visible" class="dialog-overlay" :class="customClass" @click.self="handleCloseModal">
				<div class="dialog-content" :style="dialogStyle" @click.stop>
					<div class="dialog-header">
						<div class="title-content">
							<span>{{ title }}</span>
						</div>
					</div>
					<div class="mes-dialog-layout-main">
						<slot></slot>
					</div>
					<div class="dialog-btn">
						<div v-if="showCancel && !slots['cancelText']" class="dialog-button-cancel" @click="handleCancel">
							<!-- 使用 cancelText -->
							{{ cancelText }}
						</div>
						<div v-else @click="handleCancel">
							<!-- 使用自定义插槽 -->
							<slot :name="'cancelText'"></slot>
						</div>
						<div v-if="showConfirm && !slots['confirmText']" class="dialog-button-confirm" @click="handleSure">
							<!-- 使用 confirmText -->
							{{ confirmText }}
						</div>
						<div v-else @click="handleSure">
							<!-- 使用自定义插槽 -->
							<slot :name="'confirmText'"></slot>
						</div>
					</div>
				</div>
			</div>
		</transition>
	</teleport>
	<transition name="dialog-fade" v-else>
		<div v-show="visible" class="dialog-overlay" :class="customClass" @click.self="handleCloseModal">
			<div class="dialog-content" :style="dialogStyle" @click.stop>
				<div class="dialog-header">
					<div class="title-content">
						<span>{{ title }}</span>
					</div>
				</div>
				<div class="mes-dialog-layout-main">
					<slot></slot>
				</div>
				<div class="dialog-btn">
					<div v-if="showCancel && !slots['cancelText']" class="dialog-button-cancel" @click="handleCancel">
						<!-- 使用 cancelText -->
						{{ cancelText }}
					</div>
					<div v-else @click="handleCancel">
						<!-- 使用自定义插槽 -->
						<slot :name="'cancelText'"></slot>
					</div>
					<div v-if="showConfirm && !slots['confirmText']" class="dialog-button-confirm" @click="handleSure">
						<!-- 使用 confirmText -->
						{{ confirmText }}
					</div>
					<div v-else @click="handleSure">
						<!-- 使用自定义插槽 -->
						<slot :name="'confirmText'"></slot>
					</div>
				</div>
			</div>
		</div>
	</transition>
</template>

<script lang="ts" setup>
import { ref, watch, computed, useSlots } from "vue";
const slots = useSlots();
const props = withDefaults(
	defineProps<{
		modelValue?: boolean;
		width?: string;
		height?: string;
		top?: string;
		title?: string;
		appendToBody?: boolean;
		closeOnClickModal?: boolean;
		showConfirm?: boolean;
		showCancel?: boolean;
		cancelText?: string;
		confirmText?: string;
		customClass?: string;
	}>(),
	{
		modelValue: false,
		width: "30%",
		height: "auto",
		top: "10%",
		title: "",
		appendToBody: true,
		closeOnClickModal: false,
		showConfirm: true,
		showCancel: true,
		cancelText: "取消",
		confirmText: "确认",
		customClass: ""
	}
);

const emit = defineEmits<{
	(event: "update:modelValue", value: boolean): void;
	(event: "beforeClose"): void;
	(event: "on-cancel"): void;
	(event: "on-sure"): void;
}>();

const visible = ref(props.modelValue);

watch(
	() => props.modelValue,
	newVal => {
		visible.value = newVal;
	}
);

const dialogStyle = computed(() => ({
	width: props.width,
	height: props.height,
	marginTop: props.top
}));

function handleCloseModal() {
	if (props.closeOnClickModal) {
		handleClose();
	}
}

function handleClose() {
	emit("beforeClose");
	emit("update:modelValue", false);
}

function handleCancel() {
	emit("on-cancel");
}

function handleSure() {
	emit("on-sure");
}
</script>

<style lang="scss" scoped>
.dialog-overlay {
	position: fixed;
	inset: 0;
	z-index: 9999;
	height: 100%;
	background-color: rgba(0, 0, 0, 0.7);
	overflow: auto;
	.dialog-content {
		position: relative;
		margin: 0 auto;
		background: #333333;
		border-radius: 2px;
		box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
		box-sizing: border-box;
		padding: 16px;
		overflow-wrap: break-word;
		.dialog-header {
			display: flex;
			align-items: center;
			justify-content: space-between;
			height: 40px;
			padding: 0 16px;
			border-bottom: 1px solid #6b6b6b;
			color: #ffffff;
		}
		.mes-dialog-layout-main {
			padding: 16px;
			box-sizing: border-box;
			flex: 1;
			color: #ffffff;
		}
		.dialog-btn {
			display: flex;
			justify-content: flex-end;
			padding: 10px;
			.dialog-button-cancel,
			.dialog-button-confirm {
				margin-left: 10px;
				display: inline-flex;
				justify-content: center;
				align-items: center;
				line-height: 1;
				height: 32px;
				white-space: nowrap;
				cursor: pointer;
				color: #fff;
				text-align: center;
				box-sizing: border-box;
				outline: 0;
				transition: 0.1s;
				font-weight: 500;
				-webkit-user-select: none;
				user-select: none;
				vertical-align: middle;
				background-color: #2478f2;
				border: 1px solid #dcdfe6;
				border-color: #2478f2;
				padding: 8px 15px;
				font-size: 14px;
				border-radius: 4px;
			}
		}
	}
}
</style>

<style>
.dialog-fade-enter-active,
.dialog-fade-leave-active {
	transition: opacity 0.3s ease;
}

.dialog-fade-enter,
.dialog-fade-leave-to {
	opacity: 0;
}
</style>

 使用方式:

<template>
    <Dialog
		v-model="showDialog"
		width="500px"
		title="对话框"
		@before-close="dialogBeforeClose"
		@on-sure="handleDialogSure"
		@on-cancel="handleDialogCancel"
	>
		<p>This is the dialog content</p>
	</Dialog>
</template>

<script setup lang="ts">
import { ref } from "vue";
import Dialog from "@/components/Dialog/index.vue";
const showDialog= ref(false);
const handleShowDetails = () => {
	console.log("跳转到详情页");
	showDialog.value = true;
};
const dialogBeforeClose = () => {
	console.log("对话框关闭前");
	showDialog.value = false;
};
const handleDialogSure = () => {
	console.log("对话框确认");
	showDialog.value = false;
};
const handleDialogCancel = () => {
	console.log("对话框取消");
	showDialog.value = false;
};

</script>

好的,我可以为你提供一个基本的ElDialog封装,供你参考: ```vue <template> <el-dialog :title="title" :visible.sync="dialogVisible" :before-close="handleClose" :close-on-click-modal="false" :custom-class="customClass" :width="width" :lock-scroll="lockScroll" :modal-append-to-body="modalAppendToBody" :destroy-on-close="destroyOnClose" :center="center" @opened="handleOpen" @closed="handleClosed" v-bind="$attrs" v-on="$listeners" > <slot></slot> </el-dialog> </template> <script lang="ts"> import { defineComponent } from &#39;vue&#39;; import { ElDialog } from &#39;element-plus&#39;; export default defineComponent({ name: &#39;MyDialog&#39;, props: { title: { type: String, default: &#39;&#39;, }, dialogVisible: { type: Boolean, default: false, }, customClass: { type: String, default: &#39;&#39;, }, width: { type: String, default: &#39;50%&#39;, }, lockScroll: { type: Boolean, default: true, }, modalAppendToBody: { type: Boolean, default: true, }, destroyOnClose: { type: Boolean, default: false, }, center: { type: Boolean, default: true, }, }, emits: [&#39;update:dialogVisible&#39;, &#39;opened&#39;, &#39;closed&#39;], methods: { handleClose(done: () => void) { // 自定义关闭操作 done(); }, handleOpen() { this.$emit(&#39;opened&#39;); }, handleClosed() { this.$emit(&#39;closed&#39;); }, }, components: { ElDialog, }, }); </script> ``` 这里我们使用了Vue3的Composition API,使用`defineComponent`定义了一个组件,并引入了Element Plus的ElDialog组件。 我们将ElDialog组件的属性和事件通过props和emits暴露出来,并在组件内部进行了一些自定义操作,如自定义关闭操作和自定义事件触发。 你可以根据自己的需求对组件进行进一步封装和定制化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值