Vue3+hook을 사용하여 팝업 컴포넌트를 더 빠르고 효율적으로 작성하는 방법에 대해 이야기해 보겠습니다.
왜 이런 생각을 하게 되었나요
관리 백엔드 개발 과정에서 팝업 비즈니스 팝업이 너무 많이 뜨는데, 그 중 가장 흔한 것이 "XX 데이터 추가", "XX 데이터 편집"입니다. ", "XX 상세 데이터 보기" 등의 팝업창 유형이 가장 일반적입니다. [관련 추천 : vuejs 영상 튜토리얼, 웹 프론트 엔드 개발]
이러한 팝업 구성 요소의 코드 중 구성 요소 상태, 양식 구성 요소와 관련된 메서드 등 많은 코드가 동일합니다...
그래서 , 저는 단순히 Dialog
구성 요소의 보조 캡슐화와 후크
를 사용하여 반복되는 코드를 줄입니다Dialog
组件进行的二次封装和hooks
,减少了一些重复的代码
要封装什么
如果是普通弹窗使用的话,直接使用el-dialog
组件已经足够了
但我还是一个比较爱折腾的人,我们先看看官方dialog
文档有什么可以添加的功能
...
大概看了一下,我打算封装一下功能
- 提供全屏操作按钮(右上角)
- 默认提供“确认”,“关闭”按钮
- 内部添加
Loading
效果
封装Dialog
确定了要封装的功能之后,先来一个简单的dialog
组件。
把双向绑定处理一下,这样外部就可以直接通过v-model
直接控制弹窗了。
<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>
header
这里使用到图标库@element-plus/icons-vue
如没有安装,请执行npm install @element-plus/icons-vue
使用el-dialog
提供的header
插槽,将全屏图表和关闭图标放置到右上角中。给el-dialog
传递show-close
属性关闭默认图标。
<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>
弹窗的标题文字内容通过props
进行传递,默认为空(''
)
<script lang="ts" setup> interface PropsType { // 忽略之前的代码 title?: string; } const props = withDefaults(defineProps<PropsType>(), { title: "", }); </script>
我们看看现在头部的效果(这里没传入标题,默认为''
)
现在这个按钮只有样式效果,还没有写上对应的功能 ~
给他们先绑定上对应的事件和指令
<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; }; // 关闭弹窗时向外部发送close事件 const handleClose = () => { emits("close"); }; </script>
再点击下全屏图标看看效果怎么样
NICE 头部功能也就完成了
Footer
接下来,再处理下底部内容,默认提供两个按钮,分别是“确定”和“关闭”,这个名称也是可以通过props
属性修改的。
两个按钮绑定点击事件,向外发送不同的事件。
<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>
又搞定了一部分了,就剩下Content了 ~
Content
弹窗内容通过默认插槽的方式传入进来,在外层的div
元素上添加v-loading
캡슐화할 내용If If 일반적인 팝업창에 사용되는 것이므로 el-dialog
컴포넌트를 직접 사용하면 충분합니다하지만 저는 여전히 장난을 좋아하는 사람입니다. code>dialog 문서에 어떤 기능을 추가할 수 있는지
el-dialog
컴포넌트를 직접 사용하면 충분합니다하지만 저는 여전히 장난을 좋아하는 사람입니다. code>dialog 문서에 어떤 기능을 추가할 수 있는지...loading
效果
剩下一些细节处理
在el-dialog
组件提供了很多个props
属性供用户选择,但我们现在封装的dialog
组件只使用到了一小部分props
属性。当用户想要使用其他的props
属性时该怎么办?
例如使用width属性时,难道要在我们封装的组件中接收props.width
再传递给<el-dialog :width="props.width" />
组件吗?
不不不,还有另外一种方法,还记得刚刚在做全屏操作的时候使用到的useAttrs
辅助函数吗
它可以获取当前组件传递进来的属性。有了这个方法之后,再配合并即可将外部传递进来的函数再传递到el-dialog
组件上面啦
<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>
为了避免内部传递的props被覆盖掉,
v-bind="attrs"
需要放在最前面
在使用时,可能会给before-close
属性传递一个函数,但到了后面被内部的handleClose
- 전체 화면 조작 버튼 제공(상단) 오른쪽)
- 기본적으로 "확인" 제공. "닫기" 버튼
- 내부적으로
로딩
효과 추가
대화 상자 캡슐화🎜🎜캡슐화 확인 함수 다음에는 간단한 dialog
구성 요소부터 시작하겠습니다. 🎜🎜 v-model
을 통해 팝업창을 외부에서 직접 제어할 수 있도록 양방향 바인딩을 처리합니다. 🎜<el-dialog
v-bind="attrs"
:model-value="props.modelValue"
:show-close="false"
:fullscreen="attrs?.fullscreen ?? isFullscreen"
:before-close="handleClose"
>
<!-- 忽略其他代码 -->
</el-dialog>
로그인 후 복사header🎜🎜🎜여기에서는 아이콘 라이브러리 @element-plus/icons-vue가 사용됩니다🎜🎜🎜🎜설치되지 않은 경우 npm install @element-plus를 실행하세요. /icons- vue🎜🎜🎜el-dialog
에서 제공하는 header
슬롯을 사용하여 전체 화면 차트를 배치하고 오른쪽 상단에 아이콘을 닫습니다. 기본 아이콘을 닫으려면 show-close
속성을 el-dialog
에 전달하세요. 🎜const handleClose = () => {
if (
Reflect.has(attrs, "before-close") &&
typeof attrs["before-close"] === "function"
) {
attrs["before-close"]();
}
emits("close");
};
로그인 후 복사로그인 후 복사🎜팝업창의 제목 텍스트 내용은 props
를 통해 전달되며, 기본값은 비어있습니다(''
) 🎜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,
};
}
로그인 후 복사로그인 후 복사🎜다음을 살펴보겠습니다. 현재 헤드의 효과(여기에는 전달되지 않음) 제목을 입력하세요. 기본값은 ''
)🎜🎜
🎜🎜이제 이 버튼은 스타일 효과만 있고 해당 기능은 아직 작성되지 않았습니다~🎜🎜해당 이벤트 바인딩 먼저 🎜<template>
<el-button @click="openDialog1">普通弹窗</el-button>
<DialogCmp
title="DialogCmp1"
:hiddenFullBtn="true"
v-model="visible1"
@confirm="handleConfirm"
@close="handleClose"
>
<h3 id="DialogCmp">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>
로그인 후 복사로그인 후 복사🎜 그런 다음 전체 화면 아이콘을 클릭하세요. 어떻게 작동하는지 살펴보겠습니다🎜🎜
🎜🎜NICE 이제 헤더 기능이 완성되었습니다🎜Footer🎜🎜다음으로 하단 컨텐츠 2개를 처리해 주세요. 기본적으로 "OK" 및 " "Close"가 제공되며 이 이름은 props
속성을 통해 수정할 수도 있습니다. 🎜🎜두 개의 버튼이 클릭 이벤트를 바인딩하고 다양한 이벤트를 외부로 보냅니다. 🎜export enum MODE {
ADD, EDIT,
}
로그인 후 복사로그인 후 복사🎜
🎜🎜 또 다른 부분은 완료하고 컨텐츠만 남습니다~🎜Content🎜🎜팝업 컨텐츠는 기본 슬롯을 통해 전달되고, 외부 div</를 추가합니다. <code>v-loading
태그를 code> 요소에 추가하여 로딩 상태를 달성합니다. 🎜🎜🎜팝업창 전체를 로딩효과로 연출하고 싶다면 v-loading을 가장 바깥쪽 요소로 옮겨주세요.
el-dialog 요소에 있을 수 없으며 그렇지 않으면 구현할 수 없습니다.
el-dialog가 텔레포트 구성요소를 사용하여 v-로딩이 제대로 작동하지 않을 수 있습니다.
시간나실때 공부해보세요~🎜🎜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 };
}
로그인 후 복사로그인 후 복사🎜중간에 로딩
효과를 확인해 보세요🎜🎜
🎜처리해야 할 세부 사항이 남아 있습니다🎜🎜 el-dialog</code >구성요소는 사용자가 선택할 수 있는 많은 <code>props
속성을 제공하지만, 우리가 캡슐화하고 있는 dialog
구성요소는 이제 < code>props 속성. 사용자가 다른 props
속성을 사용하려면 어떻게 해야 합니까? 🎜🎜예를 들어 width 속성을 사용할 때 캡슐화된 구성 요소에서 props.width
를 받은 다음 <el-dialog :width="props.width에 전달해야 합니까? " />< /code> 컴포넌트?🎜🎜아니요, 아니, 다른 방법이 있습니다. 전체 화면 작업을 할 때 방금 사용한 <code>useAttrs
보조 기능을 기억하시나요?🎜🎜현재 구성 요소 전송 속성에 나타납니다. 이 방법을 사용하면 외부에서 전달된 함수를 협력하여 el-dialog
컴포넌트에 전달할 수 있습니다🎜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 };
}
로그인 후 복사로그인 후 복사🎜🎜내부적으로 전달된 props가 덮어쓰이는 것을 방지하기 위해 v -bind="attrs"
는 앞쪽에 배치되어야 합니다🎜🎜🎜사용할 때 함수는 before-close
속성에 전달될 수 있지만 나중에는 내부 handlerClose
메서드가 재정의되었습니다. 🎜
<el-dialog v-bind="attrs" :model-value="props.modelValue" :show-close="false" :fullscreen="attrs?.fullscreen ?? isFullscreen" :before-close="handleClose" > <!-- 忽略其他代码 --> </el-dialog>
el-dialog
에서 제공하는 header
슬롯을 사용하여 전체 화면 차트를 배치하고 오른쪽 상단에 아이콘을 닫습니다. 기본 아이콘을 닫으려면 show-close
속성을 el-dialog
에 전달하세요. 🎜const handleClose = () => { if ( Reflect.has(attrs, "before-close") && typeof attrs["before-close"] === "function" ) { attrs["before-close"](); } emits("close"); };
props
를 통해 전달되며, 기본값은 비어있습니다(''
) 🎜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, }; }
''
)🎜🎜
<template> <el-button @click="openDialog1">普通弹窗</el-button> <DialogCmp title="DialogCmp1" :hiddenFullBtn="true" v-model="visible1" @confirm="handleConfirm" @close="handleClose" > <h3 id="DialogCmp">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>

Footer🎜🎜다음으로 하단 컨텐츠 2개를 처리해 주세요. 기본적으로 "OK" 및 " "Close"가 제공되며 이 이름은 props
속성을 통해 수정할 수도 있습니다. 🎜🎜두 개의 버튼이 클릭 이벤트를 바인딩하고 다양한 이벤트를 외부로 보냅니다. 🎜export enum MODE {
ADD, EDIT,
}
로그인 후 복사로그인 후 복사🎜
🎜🎜 또 다른 부분은 완료하고 컨텐츠만 남습니다~🎜Content🎜🎜팝업 컨텐츠는 기본 슬롯을 통해 전달되고, 외부 div</를 추가합니다. <code>v-loading
태그를 code> 요소에 추가하여 로딩 상태를 달성합니다. 🎜🎜🎜팝업창 전체를 로딩효과로 연출하고 싶다면 v-loading을 가장 바깥쪽 요소로 옮겨주세요.
el-dialog 요소에 있을 수 없으며 그렇지 않으면 구현할 수 없습니다.
el-dialog가 텔레포트 구성요소를 사용하여 v-로딩이 제대로 작동하지 않을 수 있습니다.
시간나실때 공부해보세요~🎜🎜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 };
}
로그인 후 복사로그인 후 복사🎜중간에 로딩
효과를 확인해 보세요🎜🎜
🎜처리해야 할 세부 사항이 남아 있습니다🎜🎜 el-dialog</code >구성요소는 사용자가 선택할 수 있는 많은 <code>props
속성을 제공하지만, 우리가 캡슐화하고 있는 dialog
구성요소는 이제 < code>props 속성. 사용자가 다른 props
속성을 사용하려면 어떻게 해야 합니까? 🎜🎜예를 들어 width 속성을 사용할 때 캡슐화된 구성 요소에서 props.width
를 받은 다음 <el-dialog :width="props.width에 전달해야 합니까? " />< /code> 컴포넌트?🎜🎜아니요, 아니, 다른 방법이 있습니다. 전체 화면 작업을 할 때 방금 사용한 <code>useAttrs
보조 기능을 기억하시나요?🎜🎜현재 구성 요소 전송 속성에 나타납니다. 이 방법을 사용하면 외부에서 전달된 함수를 협력하여 el-dialog
컴포넌트에 전달할 수 있습니다🎜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 };
}
로그인 후 복사로그인 후 복사🎜🎜내부적으로 전달된 props가 덮어쓰이는 것을 방지하기 위해 v -bind="attrs"
는 앞쪽에 배치되어야 합니다🎜🎜🎜사용할 때 함수는 before-close
속성에 전달될 수 있지만 나중에는 내부 handlerClose
메서드가 재정의되었습니다. 🎜
export enum MODE { ADD, EDIT, }
div</를 추가합니다. <code>v-loading
태그를 code> 요소에 추가하여 로딩 상태를 달성합니다. 🎜🎜🎜팝업창 전체를 로딩효과로 연출하고 싶다면 v-loading을 가장 바깥쪽 요소로 옮겨주세요.
el-dialog 요소에 있을 수 없으며 그렇지 않으면 구현할 수 없습니다.
el-dialog가 텔레포트 구성요소를 사용하여 v-로딩이 제대로 작동하지 않을 수 있습니다.
시간나실때 공부해보세요~🎜🎜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 }; }
로딩
효과를 확인해 보세요🎜🎜
처리해야 할 세부 사항이 남아 있습니다🎜🎜 el-dialog</code >구성요소는 사용자가 선택할 수 있는 많은 <code>props
속성을 제공하지만, 우리가 캡슐화하고 있는 dialog
구성요소는 이제 < code>props 속성. 사용자가 다른 props
속성을 사용하려면 어떻게 해야 합니까? 🎜🎜예를 들어 width 속성을 사용할 때 캡슐화된 구성 요소에서 props.width
를 받은 다음 <el-dialog :width="props.width에 전달해야 합니까? " />< /code> 컴포넌트?🎜🎜아니요, 아니, 다른 방법이 있습니다. 전체 화면 작업을 할 때 방금 사용한 <code>useAttrs
보조 기능을 기억하시나요?🎜🎜현재 구성 요소 전송 속성에 나타납니다. 이 방법을 사용하면 외부에서 전달된 함수를 협력하여 el-dialog
컴포넌트에 전달할 수 있습니다🎜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 };
}
로그인 후 복사로그인 후 복사🎜🎜내부적으로 전달된 props가 덮어쓰이는 것을 방지하기 위해 v -bind="attrs"
는 앞쪽에 배치되어야 합니다🎜🎜🎜사용할 때 함수는 before-close
속성에 전달될 수 있지만 나중에는 내부 handlerClose
메서드가 재정의되었습니다. 🎜
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 }; }
解决方案是在handleClose
函数中,获取attrs.['before-close']
属性,如果类型是函数函数,先执行它。
const handleClose = () => { if ( Reflect.has(attrs, "before-close") && typeof attrs["before-close"] === "function" ) { attrs["before-close"](); } emits("close"); };
有关于el-dialog
组件的封装就到这里了
封装hooks
利用Vue composition Api
再封装一下在使用el-dialog
组件状态的管理hook
useDialog
简单处理显示和加载态开关的hook
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, }; }
useDialog Demo
<template> <el-button @click="openDialog1">普通弹窗</el-button> <DialogCmp title="DialogCmp1" :hiddenFullBtn="true" v-model="visible1" @confirm="handleConfirm" @close="handleClose" > <h3 id="DialogCmp">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>
useDialogState 和 useDialogWithForm
useDialogState
针对开发管理后台弹窗状态封装的一个hook
,搭配下面的useDialogWithForm
使用。
export enum MODE { ADD, EDIT, }
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 }; }
useDialogWithForm
针对表单弹窗组件封装的hooks
,接收一个formRef
实例,负责控制弹窗内标题及清空表单中的校验结果,减少多余的代码 ~
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 }; }
useDialogWithForm Demo
<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>
仓库地址
如果您觉得本文对您有帮助,请帮帮忙点个star
您的反馈 是我更新的动力!
위 내용은 Vue3+hook을 사용하여 팝업 컴포넌트를 더 빠르고 효율적으로 작성하는 방법에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











vue.js에서 bootstrap 사용은 5 단계로 나뉩니다 : Bootstrap 설치. main.js.의 부트 스트랩 가져 오기 부트 스트랩 구성 요소를 템플릿에서 직접 사용하십시오. 선택 사항 : 사용자 정의 스타일. 선택 사항 : 플러그인을 사용하십시오.

HTML 템플릿의 버튼을 메소드에 바인딩하여 VUE 버튼에 함수를 추가 할 수 있습니다. 메소드를 정의하고 VUE 인스턴스에서 기능 로직을 작성하십시오.

vue.js에서 JS 파일을 참조하는 세 가지 방법이 있습니다. & lt; script & gt; 꼬리표;; mounted () 라이프 사이클 후크를 사용한 동적 가져 오기; Vuex State Management Library를 통해 수입.

vue.js의 시계 옵션을 사용하면 개발자가 특정 데이터의 변경 사항을들을 수 있습니다. 데이터가 변경되면 콜백 기능을 트리거하여 업데이트보기 또는 기타 작업을 수행합니다. 구성 옵션에는 즉시 콜백을 실행할지 여부와 DEEP를 지정하는 즉시 포함되며, 이는 객체 또는 어레이에 대한 변경 사항을 재귀 적으로 듣는 지 여부를 지정합니다.

VUE 멀티 페이지 개발은 vue.js 프레임 워크를 사용하여 응용 프로그램을 구축하는 방법입니다. 여기서 응용 프로그램은 별도의 페이지로 나뉩니다. 코드 유지 보수 : 응용 프로그램을 여러 페이지로 분할하면 코드를보다 쉽게 관리하고 유지 관리 할 수 있습니다. 모듈 식 : 각 페이지는 쉬운 재사용 및 교체를 위해 별도의 모듈로 사용할 수 있습니다. 간단한 라우팅 : 페이지 간의 탐색은 간단한 라우팅 구성을 통해 관리 할 수 있습니다. SEO 최적화 : 각 페이지에는 자체 URL이있어 SEO가 도움이됩니다.

vue.js는 이전 페이지로 돌아갈 수있는 네 가지 방법이 있습니다. $ router.go (-1) $ router.back () 사용 & lt; router-link to = & quot;/quot; Component Window.history.back () 및 메소드 선택은 장면에 따라 다릅니다.

vue.js가 트래버스 어레이 및 객체에 대한 세 가지 일반적인 방법이 있습니다. V- 결합 지시문은 V-FOR와 함께 사용하여 각 요소의 속성 값을 동적으로 설정할 수 있습니다. .MAP 메소드는 배열 요소를 새 배열로 변환 할 수 있습니다.

VUE에서 태그의 점프를 구현하는 방법에는 다음이 포함됩니다. HTML 템플릿의 A 태그를 사용하여 HREF 속성을 지정합니다. VUE 라우팅의 라우터 링크 구성 요소를 사용하십시오. javaScript 에서이. $ router.push () 메소드를 사용하십시오. 매개 변수는 쿼리 매개 변수를 통해 전달 될 수 있으며 동적 점프를 위해 라우터 옵션에서 경로가 구성됩니다.
