Element Plus的弹窗组件或View Design或大部分UI库的弹窗组件函数式封装,快速集成。
文章主要基于Vue 3针对Element Plus的dialog组件封装,其他UI组件库可做部分调整即可集成。
useDialog.ts
/**
* @author js tang
*/
import { ref } from 'vue'
export function useDialog(params: { title?: string; confirmDisabled?: boolean }) {
const visible = ref(false)
const confirming = ref(false)
const confirmDisabled = ref(params.confirmDisabled)
const mTitle = ref(params.title)
const setTitle = (title: string) => {
mTitle.value = title
}
const setConfirmDisabled = (disabled: boolean) => {
confirmDisabled.value = disabled
}
const setConfirming = (loading: boolean) => {
confirming.value = loading
}
const handleConfirm = async (callback: () => any) => {
if (confirmDisabled.value === true) { return false }
if (callback && typeof callback === 'function') {
await callback()
}
}
const handleCancel = () => {
visible.value = false
}
const handleClose = () => {
visible.value = false
}
return {
visible,
title: mTitle,
confirming,
confirmDisabled,
handleConfirm,
handleCancel,
setTitle,
setConfirmDisabled,
setConfirming,
handleClose,
}
}
使用示例
<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus'
import { useDialog } from '@/utils/useDialog' // 引入useDialog函数块
import { validateRules } from '@/utils/validateRules' // 请参考我的validateRules.js文章
import { preValidate } from '@/api/userApi'
const emit = defineEmits(['onPassed'])
const { visible, confirming, setConfirming, title, handleClose, handleConfirm } = useDialog({ title: '修改密码' })
const formRef = ref<FormInstance>()
const form = ref({
password: '',
})
const rules = ref<FormRules>({
password: [
validateRules.required('密码'),
validateRules.password('change', 'medium'),
],
})
const type = ref('')
const open = (mType: string) => {
visible.value = true
type.value = mType
}
async function handleSubmit() {
return await formRef.value && formRef.value.validate(async (valid) => {
if (valid) {
setConfirming(true)
return preValidate(form.value.password).then((data) => {
visible.value = false
emit('onPassed', { type: type.value, data })
}).finally(() => {
setConfirming(false)
})
}
})
}
watch(() => visible.value, (val) => {
if (!val) {
formRef.value.resetFields()
}
})
defineExpose({ open })
</script>
<template>
<el-dialog
v-model="visible"
:title="title"
width="30%"
:before-close="handleClose"
:close-on-click-modal="false"
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="原密码" prop="password">
<el-input v-model="form.password" type="password" placeholder="请输入密码" show-password />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button :loading="confirming" type="primary" @click="() => handleConfirm(handleSubmit)">
下一步
</el-button>
</span>
</template>
</el-dialog>
</template>
<style scoped>
</style>
useDialog包含的控制属性和事件:
属性控制:
- title // 标题
- visible // 弹窗隐藏显示控制
- confirming // 点击确定(提交)按钮的加载状态
- confirmDisabled // 可选点击确定(提交)按钮的禁用状态
方法控制:
- setTitle // 设置标题
- setConfirmDisabled // 确定(提交)按钮的禁用状态
- setConfirming // 确定(提交)按钮的加载状态
- handleConfirm // 点击提交的函数
- handleCancel // 取消弹窗
- handleClose // 关闭弹窗