
Warum haben Sie diese Idee?
Im Entwicklungsprozess des Management-Backends sind zu viele Pop-up-Business-Pop-ups beteiligt, von denen die häufigsten „XX-Daten hinzufügen“ und „XX-Daten bearbeiten“ sind „, „XX detaillierte Daten anzeigen“ und andere Popup-Fenstertypen sind am häufigsten. [Verwandte Empfehlungen: vuejs-Video-Tutorial, Web-Front-End-Entwicklung]
Viele der Codes für diese Popup-Komponenten sind gleich, z. B. Komponentenstatus, Methoden im Zusammenhang mit Formularkomponenten ...
Also , I einfach Die sekundäre Kapselung und Hooks
der Dialog
-Komponente reduzieren einige wiederholte CodesDialog
组件进行的二次封装和hooks
,减少了一些重复的代码
要封装什么
如果是普通弹窗使用的话,直接使用el-dialog
组件已经足够了
但我还是一个比较爱折腾的人,我们先看看官方dialog
文档有什么可以添加的功能
...
大概看了一下,我打算封装一下功能
- 提供全屏操作按钮(右上角)
- 默认提供“确认”,“关闭”按钮
- 内部添加
Loading
效果
封装Dialog
确定了要封装的功能之后,先来一个简单的dialog
组件。
把双向绑定处理一下,这样外部就可以直接通过v-model
直接控制弹窗了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <template>
<el-dialog :model-value= "props.modelValue" ></el-dialog>
</template>
<script setup>
interface PropsType {
modelValue?: boolean;
}
const props = withDefaults(defineProps<PropsType>(), {
modelValue: false,
});
const emits = defineEmits<{
(e: "update:modelValue" ): void;
}>();
</script>
|
Nach dem Login kopieren
header
这里使用到图标库@element-plus/icons-vue
如没有安装,请执行npm install @element-plus/icons-vue
使用el-dialog
提供的header
插槽,将全屏图表和关闭图标放置到右上角中。给el-dialog
传递show-close
属性关闭默认图标。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <template>
<el-dialog :model-value= "props.modelValue" :show-close= "false" >
<template #header>
<div>
<span>{{ props.title }}</span>
</div>
<div>
<el-icon><FullScreen /></el-icon>
<el-icon><Close /></el-icon>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { FullScreen, Close } from "@element-plus/icons-vue" ;
</script>
<style scoped>
:deep(.el-dialog__header) {
border-bottom: 1px solid #eee;
display: flex;
padding: 12px 16px;
align-items: center;
justify-content: space-between;
margin: 0;
}
.dialog-title {
line-height: 24px;
font-size: 18px;
color: #303133;
}
.btns {
display: flex;
align-items: center;
i {
margin-right: 8px;
font-size: 16px;
cursor: pointer;
}
i:last-child {
margin-right: 0;
}
}
</style>
|
Nach dem Login kopieren
弹窗的标题文字内容通过props
进行传递,默认为空(''
)
1 2 3 4 5 6 7 8 9 10 11 | <script lang= "ts" setup>
interface PropsType {
title?: string;
}
const props = withDefaults(defineProps<PropsType>(), {
title: "" ,
});
</script>
|
Nach dem Login kopieren
我们看看现在头部的效果(这里没传入标题,默认为''
)

现在这个按钮只有样式效果,还没有写上对应的功能 ~
给他们先绑定上对应的事件和指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | <template>
<el-dialog
:model-value= "props.modelValue"
:show-close= "false"
:fullscreen= "attrs?.fullscreen ?? isFullscreen"
>
<template #header>
<div>
<span class = "dialog-title" >{{ props.title }}</span>
</div>
<div class = "btns" >
<el-icon v- if = "isFullScreenBtn" @click= "handleFullscreen"
><FullScreen
/></el-icon>
<el-icon @click= "handleClose" ><Close /></el-icon>
</div>
</template>
</el-dialog>
</template>
<script setup lang= "ts" >
import { FullScreen, Close } from "@element-plus/icons-vue" ;
interface PropsType {
title?: string;
modelValue?: boolean;
hiddenFullBtn?: boolean;
}
const props = withDefaults(defineProps<PropsType>(), {
title: "" ,
modelValue: false,
hiddenFullBtn: false,
});
const emits = defineEmits<{
(e: "update:modelValue" ): void;
(e: "close" ): void;
}>();
const isFullscreen = ref(false);
const isFullScreenBtn = computed(() => {
if (props.hiddenFullBtn) return false;
if (attrs?.fullscreen) return false;
return true;
});
const handleFullscreen = () => {
if (attrs?.fullscreen) return ;
isFullscreen.value = !isFullscreen.value;
};
const handleClose = () => {
emits( "close" );
};
</script>
|
Nach dem Login kopieren
再点击下全屏图标看看效果怎么样

NICE 头部功能也就完成了
Footer
接下来,再处理下底部内容,默认提供两个按钮,分别是“确定”和“关闭”,这个名称也是可以通过props
属性修改的。
两个按钮绑定点击事件,向外发送不同的事件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | <template>
<div class = "" >
<el-dialog
v-bind= "attrs"
:model-value= "props.modelValue"
:show-close= "false"
:fullscreen= "attrs?.fullscreen ?? isFullscreen"
>
<template #footer>
<!-- 如果没有提供其他footer插槽,就使用默认的 -->
<span v- if = "!slots.footer" class = "dialog-footer" >
<el-button type= "primary" @click= "handleConfirm" >{{
props.confirmText
}}</el-button>
<el-button @click= "handleClose" >{{ props.cancelText }}</el-button>
</span>
<!-- 使用传入进来的插槽 -->
<slot v- else name= "footer" ></slot>
</template>
</el-dialog>
</div>
</template>
<script setup lang= "ts" >
import { useSlots } from "vue" ;
const slots = useSlots();
interface PropsType {
title?: string;
width?: string | number;
isDraggable?: boolean;
modelValue?: boolean;
hiddenFullBtn?: boolean;
confirmText?: string;
cancelText?: string;
}
const props = withDefaults(defineProps<PropsType>(), {
title: "" ,
isDraggable: false,
modelValue: false,
hiddenFullBtn: false,
confirmText: "确认" ,
cancelText: "关闭" ,
});
const handleClose = () => {
emits( "close" );
};
const handleConfirm = () => {
emits( "confirm" );
};
</script>
|
Nach dem Login kopieren

又搞定了一部分了,就剩下Content了 ~
Content
弹窗内容通过默认插槽的方式传入进来,在外层的div
元素上添加v-loading
标签,实现加载态。
如果你想整个弹窗实现loading效果,请把v-loading移到最外层元素即可。
注意不能是el-dialog元素上,否则无法实现
可能是el-dialog使用了teleport组件,导致v-loading无法正常工作。
等有空研究一下 ~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <template>
<div class = "" >
<el-dialog
v-bind= "attrs"
:model-value= "props.modelValue"
:show-close= "false"
:fullscreen= "attrs?.fullscreen ?? isFullscreen"
>
<div class = "content" v-loading= "props.loading" >
<slot></slot>
</div>
</el-dialog>
</div>
</template>
<script lang= "ts" setup>
interface PropsType {
loading?: boolean;
}
const props = withDefaults(defineProps<PropsType>(), {
loading: false,
});
</script>
|
Nach dem Login kopieren
试试看中间的loading
效果

剩下一些细节处理
在el-dialog
组件提供了很多个props
属性供用户选择,但我们现在封装的dialog
组件只使用到了一小部分props
属性。当用户想要使用其他的props
属性时该怎么办?
例如使用width属性时,难道要在我们封装的组件中接收props.width
再传递给<el-dialog :width="props.width" />
组件吗?
不不不,还有另外一种方法,还记得刚刚在做全屏操作的时候使用到的useAttrs
辅助函数吗
它可以获取当前组件传递进来的属性。有了这个方法之后,再配合并即可将外部传递进来的函数再传递到el-dialog
组件上面啦
1 2 3 4 5 6 7 8 9 | <el-dialog
v-bind= "attrs"
:model-value= "props.modelValue"
:show-close= "false"
:fullscreen= "attrs?.fullscreen ?? isFullscreen"
:before-close= "handleClose"
>
<!-- 忽略其他代码 -->
</el-dialog>
|
Nach dem Login kopieren
为了避免内部传递的props被覆盖掉,v-bind="attrs"
需要放在最前面
在使用时,可能会给before-close
属性传递一个函数,但到了后面被内部的handleClose
Was zu kapseln ist
🎜Wenn Wenn Es wird für gewöhnliche Popup-Fenster verwendet. Es reicht aus, die
el-dialog
-Komponente direkt zu verwenden. Aber ich bin immer noch eine Person, die gerne herumspielt. Werfen wir einen Blick auf die offizielle < code>dialog Dokumentieren Sie zuerst, welche Funktionen hinzugefügt werden können rechte Ecke)
Stellen Sie standardmäßig die Schaltfläche „Bestätigen“ bereit.Fügen Sie den Ladeeffekt
intern hinzuEncapsulate Dialog🎜🎜Confirm to encapsulate Nach der Funktion beginnen wir mit einer einfachen dialog
-Komponente. 🎜🎜 Verarbeiten Sie die bidirektionale Bindung so, dass die Außenseite das Popup-Fenster direkt über v-model
steuern kann. 🎜1 2 3 4 5 6 7 8 9 | const handleClose = () => {
if (
Reflect.has(attrs, "before-close" ) &&
typeof attrs[ "before-close" ] === "function"
) {
attrs[ "before-close" ]();
}
emits( "close" );
};
|
Nach dem Login kopieren
Nach dem Login kopieren
header🎜🎜Hier wird die Icon-Bibliothek @element-plus/icons-vue verwendet🎜
🎜Wenn diese nicht installiert ist, bitte Führen Sie npm install @element-plus/icons-vue aus🎜
🎜Verwenden Sie den von el-dialog
bereitgestellten header
-Slot, um das Vollbilddiagramm und das Schließsymbol zu platzieren in der oberen rechten Ecke. Übergeben Sie das Attribut show-close
an el-dialog
, um das Standardsymbol zu schließen. 🎜1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import { ref } from "vue" ;
export default function useDialog() {
const visible = ref(false);
const loading = ref(false);
const openDialog = () => (visible.value = true);
const closeDialog = () => (visible.value = false);
const openLoading = () => (loading.value = true);
const closeLoading = () => (loading.value = false);
return {
visible,
loading,
openDialog,
closeDialog,
openLoading,
closeLoading,
};
}
|
Nach dem Login kopieren
Nach dem Login kopieren
🎜Der Inhalt des Titeltextes des Popup-Fensters wird über props
weitergeleitet und der Standardwert ist leer (''
) 🎜1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <template>
<el-button @click= "openDialog1" >普通弹窗</el-button>
<DialogCmp
title= "DialogCmp1"
:hiddenFullBtn= "true"
v-model= "visible1"
@confirm= "handleConfirm"
@close= "handleClose"
>
<h3>DialogCmp1</h3>
</DialogCmp>
</template>
<script setup lang= "ts" >
import useDialog from "./components/useDialog" ;
import DialogCmp from "./components/Dialog.vue" ;
const {
visible: visible1,
openDialog: openDialog1,
closeDialog: closeDialog1,
} = useDialog();
</script>
|
Nach dem Login kopieren
Nach dem Login kopieren
🎜Werfen wir einen Blick darauf Wirkung des aktuellen Kopfes (hier nicht übergeben) Geben Sie den Titel ein, der Standard ist ''
)🎜🎜
🎜🎜Jetzt hat diese Schaltfläche nur noch Stileffekte und die entsprechende Funktion wurde noch nicht geschrieben~🎜🎜Binden Sie die entsprechenden Ereignisse und Anweisungen für sie zuerst🎜1 2 3 | export enum MODE {
ADD, EDIT,
}
|
Nach dem Login kopieren
Nach dem Login kopieren
🎜 Klicken Sie dann auf das Vollbildsymbol. Mal sehen, wie es funktioniert🎜🎜
🎜🎜NICE Die Header-Funktion ist jetzt abgeschlossen🎜
Footer🎜🎜Als nächstes verarbeiten Sie den unteren Inhalt werden standardmäßig bereitgestellt, nämlich „OK“ und „Close“. Dieser Name kann auch über das Attribut props
geändert werden. 🎜🎜Zwei Schaltflächen binden Klickereignisse und senden verschiedene Ereignisse aus. 🎜1 2 3 4 5 6 7 8 9 10 | import { ref } from "vue" ;
import { MODE } from "./types" ;
export default function useDialogState() {
const mode = ref<MODE>(MODE.ADD);
const visible = ref(false);
const updateMode = (target: MODE) => {
mode.value = target;
};
return { mode, visible, updateMode };
}
|
Nach dem Login kopieren
Nach dem Login kopieren
🎜
🎜🎜 Ein weiterer Teil ist erledigt, nur der Inhalt bleibt übrig~🎜
Content🎜🎜Der Popup-Inhalt wird über den Standard-Slot übergeben und der äußere div</ hinzugefügt <code>v-loading
-Tag zum Code>-Element hinzufügen, um den Ladezustand zu erreichen. 🎜🎜Wenn Sie möchten, dass das gesamte Popup-Fenster den Ladeeffekt erzielt, verschieben Sie das V-Laden bitte auf das äußerste Element.
Beachten Sie, dass es sich nicht auf dem El-Dialog-Element befinden darf, da es sonst nicht implementiert werden kann.
Es kann sein, dass el-dialog die Teleport-Komponente verwendet, was dazu führt, dass das Laden von V-Dateien nicht richtig funktioniert.
Studieren Sie es, wenn Sie Zeit haben~🎜
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { FormInstance } from "element-plus" ;
import { Ref, ref } from "vue" ;
import { MODE } from "./types" ;
import useDialogState from "./useDialogState" ;
export default function useDialogFn(
formInstance: Ref<FormInstance>
) {
const { visible, mode, updateMode } = useDialogState();
const closeDialog = () => {
formInstance.value.resetFields();
visible.value = false;
};
const openDialog = (target: MODE) => {
updateMode(target);
visible.value = true;
};
return { visible, mode, openDialog, closeDialog };
}
|
Nach dem Login kopieren
Nach dem Login kopieren
🎜Versuchen Sie, den loading
-Effekt in der Mitte zu sehen🎜🎜
🎜
Es sind noch einige Details zu klären 🎜🎜 in el-dialog
Die Komponente stellt viele props
-Attribute zur Auswahl für Benutzer bereit, aber die dialog
-Komponente, die wir derzeit kapseln, verwendet nur einen kleinen Teil davon die Eigenschaft props
. Was sollte der Benutzer tun, wenn er andere props
-Eigenschaften verwenden möchte? 🎜🎜Müssen wir beispielsweise bei Verwendung des width-Attributs props.width
in unserer gekapselten Komponente empfangen und es dann an <el-dialog :width="props.width" übergeben? " />< /code> Komponente?🎜🎜Nein, nein, es gibt einen anderen Weg. Erinnern Sie sich an die Hilfsfunktion <code>useAttrs
, die Sie gerade beim Vollbildbetrieb verwendet haben?🎜🎜Sie kann den Strom abrufen Komponentenübertragung Kommen Sie in Eigenschaften. Mit dieser Methode können Sie dann zusammenarbeiten und die von außen übergebenen Funktionen an die el-dialog
-Komponente übergeben🎜1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | <template>
<Dialog
:before-close= "customClose"
@confirm= "confirm"
v-model= "visible"
:title= "mode == MODE.ADD ? '添加数据' : '编辑信息'"
:confirm-text= "mode == MODE.ADD ? '添加' : '修改'"
>
<el-form
label-width= "100px"
:model= "formData"
ref= "formDataRef"
style= "max-width: 460px"
:rules= "rules"
>
<el-form-item label= "姓名" prop= "name" >
<el-input v-model= "formData.name" />
</el-form-item>
<el-form-item label= "年龄" prop= "age" >
<el-input v-model= "formData.age" />
</el-form-item>
<el-form-item label= "手机号码" prop= "mobile" >
<el-input v-model= "formData.mobile" />
</el-form-item>
</el-form>
</Dialog>
</template>
<script setup>
import { ElMessage, FormInstance } from "element-plus" ;
import { Ref, ref } from "vue" ;
import Dialog from "./Dialog.vue" ;
import { MODE } from "./types" ;
import useDialogWithForm from "./useDialogWithForm" ;
const rules = {
name: {
type: "string" ,
required: true,
pattern: /^[a-z]+$/,
trigger: "change" ,
message: "只能是英文名称哦" ,
transform(value: string) {
return value.trim();
},
},
age: {
type: "string" ,
required: true,
pattern: /^[0-9]+$/,
trigger: "change" ,
message: "年龄只能是数字哦" ,
transform(value: string) {
return value.trim();
},
},
mobile: {
type: "string" ,
required: true,
pattern:
/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/,
trigger: "change" ,
message: "请输入正确的手机号码" ,
transform(value: string) {
return value.trim();
},
},
};
interface FromDataType {
name: string;
age: string;
mobile: string;
}
const formDataRef = ref<FormInstance | null>(null);
let formData = ref<FromDataType>({
name: "" ,
age: "" ,
mobile: "" ,
});
const { visible, closeDialog, openDialog, mode } = useDialogWithForm(
formDataRef as Ref<FormInstance>
);
const confirm = () => {
if (!formDataRef.value) return ;
formDataRef.value.validate((valid) => {
if (valid) {
console.log( "confirm" );
ElMessage({
message: "提交成功" ,
type: "success" ,
});
closeDialog();
}
});
};
const customClose = () => {
ElMessage({
message: "取消提交" ,
type: "info" ,
});
closeDialog();
};
defineExpose({
closeDialog,
openDialog,
});
</script>
<style scoped></style>
|
Nach dem Login kopieren
Nach dem Login kopieren
🎜Um zu verhindern, dass die intern übergebenen Requisiten überschrieben werden, v-bind="attrs"
muss vorne platziert werden🎜
🎜Bei Verwendung kann eine Funktion an das Attribut before-close
übergeben werden, dies wird jedoch der Fall sein Die interne Methode handleClose
wird überschrieben. 🎜
解决方案是在handleClose
函数中,获取attrs.['before-close']
属性,如果类型是函数函数,先执行它。
1 2 3 4 5 6 7 8 9 | const handleClose = () => {
if (
Reflect.has(attrs, "before-close" ) &&
typeof attrs[ "before-close" ] === "function"
) {
attrs[ "before-close" ]();
}
emits( "close" );
};
|
Nach dem Login kopieren
Nach dem Login kopieren
有关于el-dialog
组件的封装就到这里了
封装hooks
利用Vue composition Api
再封装一下在使用el-dialog
组件状态的管理hook
useDialog
简单处理显示和加载态开关的hook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import { ref } from "vue" ;
export default function useDialog() {
const visible = ref(false);
const loading = ref(false);
const openDialog = () => (visible.value = true);
const closeDialog = () => (visible.value = false);
const openLoading = () => (loading.value = true);
const closeLoading = () => (loading.value = false);
return {
visible,
loading,
openDialog,
closeDialog,
openLoading,
closeLoading,
};
}
|
Nach dem Login kopieren
Nach dem Login kopieren
useDialog Demo

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <template>
<el-button @click= "openDialog1" >普通弹窗</el-button>
<DialogCmp
title= "DialogCmp1"
:hiddenFullBtn= "true"
v-model= "visible1"
@confirm= "handleConfirm"
@close= "handleClose"
>
<h3>DialogCmp1</h3>
</DialogCmp>
</template>
<script setup lang= "ts" >
import useDialog from "./components/useDialog" ;
import DialogCmp from "./components/Dialog.vue" ;
const {
visible: visible1,
openDialog: openDialog1,
closeDialog: closeDialog1,
} = useDialog();
</script>
|
Nach dem Login kopieren
Nach dem Login kopieren
useDialogState 和 useDialogWithForm
useDialogState
针对开发管理后台弹窗状态封装的一个hook
,搭配下面的useDialogWithForm
使用。
1 2 3 | export enum MODE {
ADD, EDIT,
}
|
Nach dem Login kopieren
Nach dem Login kopieren
1 2 3 4 5 6 7 8 9 10 | import { ref } from "vue" ;
import { MODE } from "./types" ;
export default function useDialogState() {
const mode = ref<MODE>(MODE.ADD);
const visible = ref(false);
const updateMode = (target: MODE) => {
mode.value = target;
};
return { mode, visible, updateMode };
}
|
Nach dem Login kopieren
Nach dem Login kopieren
useDialogWithForm
针对表单弹窗组件封装的hooks
,接收一个formRef
实例,负责控制弹窗内标题及清空表单中的校验结果,减少多余的代码 ~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | import { FormInstance } from "element-plus" ;
import { Ref, ref } from "vue" ;
import { MODE } from "./types" ;
import useDialogState from "./useDialogState" ;
export default function useDialogFn(
formInstance: Ref<FormInstance>
) {
const { visible, mode, updateMode } = useDialogState();
const closeDialog = () => {
formInstance.value.resetFields();
visible.value = false;
};
const openDialog = (target: MODE) => {
updateMode(target);
visible.value = true;
};
return { visible, mode, openDialog, closeDialog };
}
|
Nach dem Login kopieren
Nach dem Login kopieren
useDialogWithForm Demo

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | <template>
<Dialog
:before-close= "customClose"
@confirm= "confirm"
v-model= "visible"
:title= "mode == MODE.ADD ? '添加数据' : '编辑信息'"
:confirm-text= "mode == MODE.ADD ? '添加' : '修改'"
>
<el-form
label-width= "100px"
:model= "formData"
ref= "formDataRef"
style= "max-width: 460px"
:rules= "rules"
>
<el-form-item label= "姓名" prop= "name" >
<el-input v-model= "formData.name" />
</el-form-item>
<el-form-item label= "年龄" prop= "age" >
<el-input v-model= "formData.age" />
</el-form-item>
<el-form-item label= "手机号码" prop= "mobile" >
<el-input v-model= "formData.mobile" />
</el-form-item>
</el-form>
</Dialog>
</template>
<script setup>
import { ElMessage, FormInstance } from "element-plus" ;
import { Ref, ref } from "vue" ;
import Dialog from "./Dialog.vue" ;
import { MODE } from "./types" ;
import useDialogWithForm from "./useDialogWithForm" ;
const rules = {
name: {
type: "string" ,
required: true,
pattern: /^[a-z]+$/,
trigger: "change" ,
message: "只能是英文名称哦" ,
transform(value: string) {
return value.trim();
},
},
age: {
type: "string" ,
required: true,
pattern: /^[0-9]+$/,
trigger: "change" ,
message: "年龄只能是数字哦" ,
transform(value: string) {
return value.trim();
},
},
mobile: {
type: "string" ,
required: true,
pattern:
/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[189]))\d{8}$/,
trigger: "change" ,
message: "请输入正确的手机号码" ,
transform(value: string) {
return value.trim();
},
},
};
interface FromDataType {
name: string;
age: string;
mobile: string;
}
const formDataRef = ref<FormInstance | null>(null);
let formData = ref<FromDataType>({
name: "" ,
age: "" ,
mobile: "" ,
});
const { visible, closeDialog, openDialog, mode } = useDialogWithForm(
formDataRef as Ref<FormInstance>
);
const confirm = () => {
if (!formDataRef.value) return ;
formDataRef.value.validate((valid) => {
if (valid) {
console.log( "confirm" );
ElMessage({
message: "提交成功" ,
type: "success" ,
});
closeDialog();
}
});
};
const customClose = () => {
ElMessage({
message: "取消提交" ,
type: "info" ,
});
closeDialog();
};
defineExpose({
closeDialog,
openDialog,
});
</script>
<style scoped></style>
|
Nach dem Login kopieren
Nach dem Login kopieren
仓库地址
useDialog
在线demo地址

如果您觉得本文对您有帮助,请帮帮忙点个star
您的反馈 是我更新的动力!
(学习视频分享:vuejs入门教程、编程基础视频)
Das obige ist der detaillierte Inhalt vonLassen Sie uns darüber sprechen, wie Sie mit Vue3+Hook Popup-Komponenten schneller und effizienter schreiben können. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!