功能和作用介绍
通过指令式的hooks方法弹窗弹出自己写的任意组件,可以弹出一个全局表单,或者全局树(通讯录)这种弹窗,在确认时拿到所需的数据。
描述就不多描述了,我也只是个菜鸟,更多的是只会用,不太了解为什么。 直接放代码了,不足之处请指出,有些方法我觉得可以优化,但是没琢磨出来。
灵感及方法来源于:Vue3 组件封装进阶,简简单单实现一个弹窗表单组件 - 掘金 (juejin.cn)
效果演示
代码实现
hooks方法
js
import {h} from 'vue'
import {Modal} from 'ant-design-vue'
const useModalHooks = options => {
return new Promise((resolve, reject) => {
const onOk = close => {
const exposed = vNode.component.exposed
exposed.onHandleSubmit(resolve, close)
}
const onCancel = () => {
reject({errMsg: '取消', error: false})
}
options.modalApi = options.modalApi || {} // modal的api
options.props = options.props || {} // 组件传递参数
const vNode = h(options.content, {options: options.props})
Modal.confirm({
icon: null,
content: vNode,
closable: true,
...options.modalApi,
onOk,
onCancel
})
})
}
export default useModalHooks
组件中注意事项
组件中必须含有且暴露出这个方法,这个方法与hooks中onOk中定义的方法一致。 用h函数渲染的组件中第三方UI组件库内部需要重新引用
在确认操作中我们可以在这个方法中操作这个组件的方法与数据(比如校验、请求等等)
用 resolve 将想要传递的数据传递出去,close 决定是否关闭这个弹窗
vue
<template>
<a-form class="login-form" ref="formStateRef" :model="formState" name="basic" autocomplete="off">
<a-form-item name="username" :rules="[{required: true, message: '请输入账号!'}]">
<a-input v-model:value="formState.username" allowClear size="large" placeholder="请输入账号">
<template #prefix><UserOutlined style="color: rgba(0, 0, 0, 0.25)" /></template>
</a-input>
</a-form-item>
<a-form-item name="password" :rules="[{required: true, message: '请输入密码!'}]">
<a-input-password
type="password"
v-model:value="formState.password"
allowClear
size="large"
placeholder="请输入密码"
>
<template #prefix><LockOutlined style="color: rgba(0, 0, 0, 0.25)" /></template>
</a-input-password>
</a-form-item>
</a-form>
</template>
<script setup>
import {ref, reactive, onMounted} from 'vue'
import {LockOutlined, UserOutlined} from '@ant-design/icons-vue'
import {Form as AForm, FormItem as AFormItem, Input as AInput, InputPassword as AInputPassword} from 'ant-design-vue'
const props = defineProps(['options'])
console.log(props.options)
const formState = reactive({
username: '',
password: '',
repassword: '',
remember: false
})
const onSubmit = () => {
console.log('登录')
}
const formStateRef = ref()
const onHandleSubmit = (resolve, close) => {
formStateRef.value
.validate()
.then(() => {
resolve(JSON.parse(JSON.stringify(formState)))
close()
})
.catch(error => {
return false
})
}
defineExpose({onHandleSubmit})
</script>
<style scoped lang="less"></style>
使用hooks方法
方法的使用无非就是引入传参
vue
<template>
<a-button class="page-btn" type="primary" @click="openTestAppModal">测试打开弹窗</a-button>
</template>
<script setup>
import useModalHooks from '@/hooks/useModalHooks'
import TestForm from '@/components/TestForm.vue'
const openTestAppModal = () => {
useModalHooks({
content: TestForm,
modalApi: {
title: '测试'
},
props: {
a: 1,
b: 2
}
})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
})
}
</script>
<style scoped lang="less"></style>
事实上我写完曾怀疑是不是多此一举了,因为antdv的modal这个方法本身就可以渲染组件,不过想来可能不能直接获取这个组件的数据吧,或许是我不太了解h函数的具体使用。