在我们日常开发中已经遇到各种弹框,今天封装了一套可拖拽弹框,开箱可用:
在componnets下新建Dialog文件, 里面再建index.vue,代码如下:
<script setup>
const props = defineProps({
appendToBody: {
type: Boolean,
default: false,
},
lockScroll: {
type: Boolean,
default: true,
},
width: {
type: [String, Number],
default: '50%',
},
modelValue: {
type: Boolean,
default: false,
},
title: {
type: String,
default: '',
},
showClose: {
type: Boolean,
default: true,
},
showFullscreen: {
type: Boolean,
default: false,
},
draggable: {
type: Boolean,
default: true,
},
loading: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue'])
const dialogVisible = useVModel(props, 'modelValue', emit)
const isFullscreen = ref(false)
const closeDialog = () => {
dialogVisible.value = false
}
const setFullscreen = () => {
isFullscreen.value = !isFullscreen.value
}
</script>
<template>
<div class="main-dialog">
<el-dialog
v-model="dialogVisible"
v-bind="$attrs"
:append-to-body="appendToBody"
:draggable="draggable"
:fullscreen="isFullscreen"
:lock-scroll="lockScroll"
:show-close="false"
:width="width"
>
<template #header>
<slot name="header">
<span class="el-dialog__title">{{ title }}</span>
</slot>
<div class="main-dialog__headerbtn">
<button
v-if="showFullscreen"
aria-label="fullscreen"
type="button"
@click="setFullscreen"
>
<el-icon v-if="isFullscreen" icon="fullscreen-exit-line" />
<el-icon v-else icon="fullscreen-line" />
</button>
<button
v-if="showClose"
aria-label="close"
type="button"
@click="closeDialog"
>
<el-icon icon="close-circle-line" />
</button>
</div>
</template>
<div v-loading="loading">
<slot></slot>
</div>
<template #footer>
<slot name="footer"></slot>
</template>
</el-dialog>
</div>
</template>
<style lang="scss" scoped>
.main-dialog {
&__headerbtn {
position: absolute;
top: var(--el-dialog-padding-primary);
right: var(--el-dialog-padding-primary);
}
button {
padding: 0;
margin-left: 15px;
font-size: var(--el-message-close-size, 16px);
color: var(--el-color-info);
cursor: pointer;
background: transparent;
border: none;
outline: none;
transition: $base-transition;
&:hover i {
color: var(--el-color-primary);
}
}
:deep(.el-dialog) {
&.is-fullscreen {
top: 0px !important;
left: 0px !important;
display: flex;
flex-direction: column;
.el-dialog__body {
flex: 1;
overflow: auto;
}
.el-dialog__footer {
padding-bottom: 10px;
border-top: 1px solid var(--el-border-color-base);
}
}
}
}
</style>
用法如下:
- 新建DialogDemo引入dialog组件, 绑定v-model
<template>
<mian-dialog
v-model="dialogVisible"
show-fullscreen
title="测试title"
width="600px"
>
我是内容展示
<template #footer>
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</template>
</vab-dialog>
</template>
<script>
import MainDialog from '@/components/Dialog'
export default defineComponent({
name: 'DialogDemo',
components: {
MainDialog,
},
setup() {
const state = reactive({
dialogVisible: false,
})
return {
...toRefs(state),
}
},
})
</script>
<style></style>
组件使用
<template>
<div class="dialog-drag-container">
<el-button type="primary" @click="handleClick">可拖拽弹窗</el-button>
<dialog-demo ref="dialogRef" />
</div>
</template>
<script>
export default defineComponent({
name: 'DialogDrag',
components: {
DialogDemo: defineAsyncComponent(() => import('./components/DialogDemo')),
},
setup() {
const state = reactive({
dialogRef: '',
})
const handleClick = () => {
state['dialogRef'].dialogVisible = true
}
return {
...toRefs(state),
handleClick,
}
},
})
</script>
- 以上就是完整代码, 赋值即可查看效果,如有不足,欢迎大家补充