升级Vue3.4.x版本,ant-design-vue 3.x 版本的Modal函数方式无法关闭问题

2025/9/8 vue3ant-design-vue

# 前言

先说结论:Vue版本固定在v3.3,ant-design-vue版本固定为v3.x。除非ant-design-vue也升级,否则**Vue版本也不要动。

后文为遇见问题的详细记录,可选看

# 升级Vue为v3.4.x出现问题

当前Vue版本为3.3.x,想升级Vue到3.4.x版本,但升级后,ant-design-vue 3.x 版本的Modal函数方法有问题,如Modal.confirm打开后,取消确认按钮回调能执行,但是弹窗却无法关闭

于是到github的ant-design-vue库找的相关issue #7375 (opens new window) #7239 (opens new window)

ant-design-vue团队合并了pr (opens new window)并关掉了相关issue,但是修复代码只在4.x版本后,3.x仍存在该问题。相关修复如下:

alt text alt text

而升级ant-design-vue 4.x是破坏性升级,涉及到很多地方变动,没有办法升级。所以当时的解决方案是:Vue版本固定在v3.3,ant-design-vue版本固定为v3.x

# 升级Vue为v3.5.x可解决该问题(不过后升级后发现存在其他问题)

因为还是想用Vue3.4的新特性,有空时去看ant-design-vue的issue,看会不会针对3.x版本修复这一问题,但应该是不会有的,不过发现有条评论说“Vuev3.5.13修复了这一问题”

然后就去升级试试,发现是v3.5.0修复了,升级v3.5.x后Modal.confirm弹窗顺利关闭了

但是升级为v3.5.x还是会有其他问题(25.11.14更新,具体看后文)

# v3.5是怎么解决的弹窗关闭的?

好奇v3.5是怎么解决的,就去github上看Vue的相关issue,看到有人提到和ant-design-vue相关问题 (opens new window),不过看Vue的v3.5.0更新日志 (opens new window)并没有提到这一issue,也没有找到其他相关更新说明

就根据ant-design-vue的修复代码,推测是Vue v3.4被改动的update方法,在v3.5又改回来了

alt text

然后就去看Vue源码,推测相关改动(没有完整看完源码,是凭借关键字和代码提交时间推测的)

看下图代码改动,可以看出3.4版本判断了effect.dirty才去执行的,而3.4前和3.5后都是没有判断的。3.5后增加了jobrunIfDirty执行,而update改回为无判断执行

左边为3.4后提交的,右边为3.5后提交的 alt text

左边为3.4前提交的,右边为3.4后提交的 alt text

# 升级后存在的其他问题

问题:

vue版本v3.5.xant-design-vue3.2.20

使用Table组件时,同时使用#header#expandedRowRender的时候,页面点击展开会报错,造成展开失败

不过并不总是每次都报错,是没有使用v-model:expanded-row-keys="expandedRowKeys"去控制,由默认处理的时候报错。也不是每次报错都会展开失败,有的页面是出现报错了,但是展开成功了,或者多点几次就展开正常了。

报错如图所示,我在ant-design-vue3.2.20 tag的demo中测试,不过vue核心库的版本是@vue/runtime-core@3.5.22,就在basic的表格上,其原有#header,再加上了#expandedRowRender,此时点击展开就会报以下错误。大概是使用这个vue版本核心库的错误

alt text alt text

解决:

  • 去掉#header就不报错了,但不能去掉#header功能啊

  • ant-design-vue的4.x版本也不报错,但从3.x升到4.x改动太多了,就算开发能批量改,测试也没法测全,所以也没法升级。ant-design-vue也不可能针对3.x修复问题。

  • 使用v-model:expanded-row-keys="expandedRowKeys"去控制,但是这样每个用到的都要改,改动太多,不过可以作为降级前的临时方案

  • 降级vue版本回3.3.x也没问题,最后就只能采取这个最稳的做法了

# 其他

vue3.3升级到vue3.5的新特性,具体可看更新文档

3.4更新文档 (opens new window)翻译版:https://juejin.cn/post/7317809451187208218?searchId=20250902174214673E19C04CEE8A1C2F50 (opens new window)

3.5更新文档 (opens new window)翻译版:https://juejin.cn/post/7410316451962142731?searchId=20250902175718A2E7B5955736D621881D (opens new window)

其中比较有用的api

defineModel()

3.4新增defineModel(),更方便地定义双向绑定,具体可看文档 (opens new window)

在之前的版本,双向绑定是通过definePropsdefineEmits,有时再结合使用vueuse中的useVModel完成。

在3.4就可以直接使用一个defineModel()更快速的实现了,其底层辅助函数是useModel() (opens new window)

// 一般写法
const isVisible = defineModel('visible', {
  type: Boolean,
  required: true,
})
// 用ts的写法
const isVisible = defineModel<boolean>('visible', { required: true })

# Props 解构默认值

3.5+新增Props解构默认值,更方便地设置默认值,具体可看文档 (opens new window)

在之前的版本,props解构的写法并不能设置默认值,所以是用withDefaults设置默认值。

在3.5+后就可以直接以解构的方式设置来默认值,且仍可以保留响应式。

如果担心用解构写法后不好区分props,可以在Vue (Official)插件设置开启相关提示

alt text

注意:升级3.5后withDefaults仍可使用,但不要在同一个props同时使用解构和withDefaults

# useTemplateRef()

3.5+ 新增useTemplateRef()获取模板引用

在之前的版本,使用与静态 ref属性名称匹配的普通引用。

在3.5+后就可以使用useTemplateRef() ,在运行时字符串ID匹配引用,因此支持将动态引用绑定到变化的ID

结合插件的升级,会有模板引用字符串的提示和组件相关提示,开发体验更好

alt textalt text

# watch 监听函数相关

once:(3.4+) 回调函数只会运行一次。第三个可选的参数增加了once,侦听器将在回调函数首次运行后自动停止。

watch(
  source,
  (newValue, oldValue) => {
    // 当 `source` 变化时,仅触发一次
  },
  { once: true }
)

stop, pause, resume :(3.5+) 暂停/恢复侦听器

const { stop, pause, resume } = watch(() => {})

// 暂停侦听器
pause()

// 稍后恢复
resume()

// 停止
stop()
上次更新: 2025/11/17 06:46:49
CHANGE THE WORLD
v6