Vue3+Quasar中等待弹窗按钮点击续行函数及TS空值错误排查
问题:Vue3 + Quasar弹窗等待按钮点击后执行后续逻辑失败,触发TypeScript错误
我有一个带弹窗对话框(含按钮)的函数,希望等待按钮点击后再执行函数剩余逻辑。尝试用Promise和addEventListener实现但没成功,还遇到TypeScript错误:Object is possibly 'null'.ts(2531)。使用Vue3和Quasar框架,相关代码如下:
模板代码
<q-dialog persistent v-model="phoneDialogBank"> <q-card> <q-card-section> <div class="items" v-for="formField in dynamicDialogFieldsVisible" :key="formField?.Key"> <dynamic-form-field :form-field="formField"></dynamic-form-field> </div> <div class="row items-center justify-center"> <q-btn color="primary" class="confirm-phone-dialog" v-close-popup> {{ t('signing-table.phoneDialogBank.ok') }} </q-btn> </div> </q-card-section> </q-card> </q-dialog>
函数代码
async function dynamicDialogBeforeSubmit() { const params = getParamsFromAdvisorDeviceBoolean(); if (params && params.hasOwnProperty('dialogBeforeSubmit') && params.dialogBeforeSubmit) { phoneDialogBank.value = true; const confirm = document.querySelector('.confirm-phone-dialog'); const waitForButtonClick = new Promise((resolve) => { confirm.addEventListener('click', resolve); }); await waitForButtonClick.then(() => { dynamicDialogSave(); }); return; } dynamicDialogSave(); }
解决方案
1. 先解决TypeScript的null报错
document.querySelector('.confirm-phone-dialog')可能返回null,TypeScript会提示风险,两种处理方式:
- 非空断言(需确保弹窗显示后元素一定存在):
const confirm = document.querySelector('.confirm-phone-dialog')!; - 安全判断(更严谨):
const confirm = document.querySelector('.confirm-phone-dialog'); if (!confirm) { dynamicDialogSave(); return; }
2. 修复原生DOM监听失效问题,改用Vue响应式方案
原生DOM监听失效大概率是因为弹窗显示时DOM还没渲染完成,导致querySelector找不到元素。同时直接绑定监听还会有重复绑定的风险,建议用Vue的事件绑定+Promise封装:
第一步:修改模板,给确认按钮添加点击事件
<q-dialog persistent v-model="phoneDialogBank" @hide="resetDialogResolver"> <q-card> <q-card-section> <div class="items" v-for="formField in dynamicDialogFieldsVisible" :key="formField?.Key"> <dynamic-form-field :form-field="formField"></dynamic-form-field> </div> <div class="row items-center justify-center"> <q-btn color="primary" class="confirm-phone-dialog" v-close-popup @click="confirmDialog"> {{ t('signing-table.phoneDialogBank.ok') }} </q-btn> </div> </q-card-section> </q-card> </q-dialog>
第二步:重构函数逻辑
// 用于存储Promise的resolve函数 let dialogResolve: (value?: unknown) => void; // 按钮点击时触发resolve const confirmDialog = () => { dialogResolve?.(); }; // 弹窗关闭时清空resolve,避免内存泄漏 const resetDialogResolver = () => { dialogResolve = undefined; }; async function dynamicDialogBeforeSubmit() { const params = getParamsFromAdvisorDeviceBoolean(); // 简化判断逻辑 if (params?.dialogBeforeSubmit) { phoneDialogBank.value = true; // 封装等待确认的Promise const waitForConfirm = new Promise(resolve => { dialogResolve = resolve; }); await waitForConfirm; dynamicDialogSave(); return; } dynamicDialogSave(); }
这种方式完全基于Vue的响应式和事件系统,避免了原生DOM操作的弊端,也能确保等待逻辑可靠执行。
内容的提问来源于stack exchange,提问作者David Henzl
相关产品推荐
相关产品推荐

