在new Promise作用域外更改状态
假设你有多个页面的一些功能需要先收集用户的信息才能允许使用,在点击使用某功能前先弹出信息收集的弹框,你会怎么实现呢?
-
创建收集信息的弹窗组件
<template>
<el-dialog
:modelValue="isShowUserInfo"
title="Warning"
width="500"
align-center
>
<el-form :model="form" label-width="120px">
<el-form-item label="用户名">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.password" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">同意</el-button>
<el-button @click="onCancel">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
</template>
<script setup>
import { ref } from 'vue'
defineProps({
isShowUserInfo: Boolean
})
const form = ref({ name: '', password: '' })
const emit = defineEmits(['onSubmit', 'onCancel'])
const onSubmit = () => {
emit('onSubmit', form.value)
}
const onCancel = () => {
emit('onCancel', 'onCancel')
}
</script>
<style lang="scss" scoped></style>
-
封装hooks
import { provide, ref } from 'vue'
const useGetInfo = () => {
const isShowUserInfo = ref(false)
let resolveFn, rejectFn
provide('getInfo', () => {
isShowUserInfo.value = true
return new Promise((resolve, reject) => {
resolveFn = resolve
rejectFn = reject
})
})
const onSubmit = (value) => {
isShowUserInfo.value = false
resolveFn && resolveFn(value)
}
const onCancel = (value) => {
isShowUserInfo.value = false
rejectFn && rejectFn(new Error(value))
}
return {
isShowUserInfo,
onSubmit,
onCancel
}
}
export default useGetInfo
-
在父级页面注册弹窗组件
<script setup>
import userInfoCom from '@/components/userInfoCom.vue'
import useGetInfo from '@/hooks/useGetInfo'
const { isShowUserInfo, onSubmit, onCancel } = useGetInfo()
</script>
<template>
<router-view></router-view>
<user-info-com
:isShowUserInfo="isShowUserInfo"
@onSubmit="onSubmit"
@onCancel="onCancel"
></user-info-com>
</template>
-
需要使用的组件只需inject
const getInfo = inject('getInfo')
const handelClick = async () => {
try {
const res = await getInfo()
console.log(res)
} catch (error) {
console.dir(error.message)
}
}
<template>
<el-button type="primary" @click="handelClick">showUserInfo</el-button>
</template>