Vue/Vuetify中点击按钮后点击事件丢失问题求助
生产环境下Vuetify弹窗仅能打开一次的问题排查
问题现象
- 基于Vuetify开发的弹窗组件,通过按钮触发打开,完成操作后可关闭
- 开发环境:关闭弹窗后可再次正常打开
- 生产环境:弹窗仅能打开一次,首次点击按钮后DOM/Window上的点击事件被移除
技术栈
- Vue 2
- Vuetify 2.7
- 项目包含部分旧jQuery代码
排查线索
- 打开弹窗时整个组件会触发重渲染
- 移除弹窗标签页中加载的所有组件后,问题不再出现
弹窗容器代码
<template> <div> <v-tooltip left> <template #activator="{ on, attrs }"> <v-btn class="o-page-sidebar__button create-project__button" color="#009688" dark depressed tile v-bind="attrs" v-on="on" @click="triggerModal(undefined)" > <v-icon size="16"> fal fa-clipboard-list </v-icon> </v-btn> </template> <span>{{ translations.title }}</span> </v-tooltip> <CreateProjectModal v-if="showModal" v-bind="$attrs" v-model="showModal" :translations="translations" @hasEditedProject="handleHasEditedProject" @hasCreatedProject="handleHasCreatedProject" /> </div> </template> <script> export default { data() { return { showModal: false, }; }, methods: { triggerModal(eventObject) { if (eventObject == undefined) { eventObject = {}; } const localStorageValue = localStorage.useNewCreateProjectDialog != undefined ? localStorage.useNewCreateProjectDialog == 'true' : true; const openRequest = { Type: eventObject.type, ProjectID: eventObject.projectID, OfferID: eventObject.offerID, DebtorID: eventObject.debtorID, FitterID: eventObject.fitterID, ManagerID: eventObject.managerID, PlanningStartDate: eventObject.planningStartDate, PlanningEndDate: eventObject.planningEndDate }; this.notification.show = false; if (localStorageValue) { const type = eventObject.type ? eventObject.type : 'CreateProject'; openRequest.Type = this.openProjectDialogEnum.find(x => x.Name == type)?.Name; this.$store.dispatch('setOpenRequest', openRequest); this.$store.dispatch('setHasInitializedFields', { 'MainProjectID': false, 'OfferID': false, 'ProjectDebtorID': openRequest.Type != 'EditProject', 'ProjectGroupID': openRequest.Type != 'EditProject' }); this.showModal = true; } } } </script>
弹窗组件代码
<template> <v-dialog v-model="show" :class="{ 'new-create-project' : show }" fullscreen :retain-focus="false" hide-overlay persistent no-click-animation height="100vh" transition="dialog-bottom-transition" @keydown.esc="confirmClose" > {{ ... }} </v-dialog> </template> <script> export default { props: { value: { type: Boolean, default: false }, }, computed: { show: { get() { return this.value; }, set(value) { if (!value) { this.$store.dispatch('setNotifications', []); this.$store.dispatch('setSelectedDebtor', null); this.$store.dispatch('emptyErrors'); } this.$store.dispatch('resetProjectData'); this.$emit('input', value); } }, } } </script>
标签页加载代码
<v-tabs ref="tabs" v-model="currentTab" v-shortkey.once="{save: ['ctrl', 'q'], saveAndPrint: ['alt', 'q'], tabRight: ['alt', 'arrowright'], tabLeft: ['alt', 'arrowleft']}" grow @shortkey.native="handleShortcuts" > <v-tab v-for="(tab, i) in mappedTabs" :key="i" :disabled="(tab.canDisable && !enableTabs) || tab.disabled" > <v-icon left> {{ tab.icon }} </v-icon> {{ tab.name }} <v-icon v-if="tab.hasErrors" size="14" color="error" class="ml-2" > fa fa-exclamation-triangle </v-icon> </v-tab> </v-tabs> </v-card-text> <v-tabs-items v-model="currentTab" class="grow d-grid" > <v-card-text class="fill-height"> <v-tab-item v-for="(tab, i) in mappedTabs" :key="`${i}-item`" class="fill-height" > <component :is="tab.component" :is-active="currentTab === i" v-bind="$attrs" from-create-project class="create-project__form" @show-association="showAssociation" @set-contact-person="setContactPerson" @set-work-address="setWorkAddress" /> </v-tab-item> </v-card-text> </v-tabs-items>
标签页示例代码
{ name: this.translations.tabProjectInformation, hasErrors: this.$store.getters.hasProjectInformationErrors, icon: 'fal fa-clipboard-list', component: 'ProjectInformation' },
内容的提问来源于stack exchange,提问作者Ayice
相关产品推荐
相关产品推荐

