antUI a-tag动态删除选项疑点?

需求

使用ant的a-tag,做了一个多选项(非下拉多选框组件)即页面平铺展示。这个selectData数组是一个动态的,根据用户选择不同而不同。

疑点

当用户想删除某个选项时,如测试二(id:"456")时,会把后面的测试三(id:"789")也删除,但打印数组结果是正常的,显示却只有一个测试一(id:"123")在页面上。

  
用户选择的数组
selectData:[
  {id:"123",name:"测试一"},
  {id:"456",name:"测试二"},
  {id:"789",name:"测试三"}
]
删除后打印的数组
selectData:[
  {id:"123",name:"测试一"},
  {id:"789",name:"测试三"}
]

使用的删除方法
tagClose(ele) {
  const arr = this.selectData
  const res = arr.filter((item) => item.id !== ele.id)
  this.selectData = res //问题就在这里过滤后进行赋值,为什么就会出现删除其后面的选项
},

后来试试重载方法就正常了,这是为什么啊?
tagClose(ele) {
  const arr = this.selectData
  const res = arr.filter((item) => item.id !== ele.id)
  this.loadPage()
  this.selectData = res
},

代码

<div class="selectInput" v-if="loadingCom">
        <a-tag closable @close="tagClose(item)" v-for="(item, index) in selectData" :key="index" style="maring-top: 3px"
          >{{ item.name }}
        </a-tag>
</div>

删除选项事件

tagClose(ele) {
  console.log('🚀 ~ tagClose ~ ele:', ele.id)
  const arr = this.selectData
  const res = arr.filter((item) => item.id !== ele.id)
  this.loadPage()
  this.selectData = res
  console.log('🚀 ~ this.selectData.filter ~  this.selectData:', res)
},

使用重载方法
 loadingCom() {
  this.loadingCom = false
  this.$nextTick(function () {
    this.loadingCom = true
  })
},
阅读 885
avatarAI BotBETA

回答

问题出现在 Vue 的响应式系统更新机制上。当你直接修改 this.selectData 时,虽然数组的内容已经正确更新(如你所见,打印的数组结果是正常的),但 Vue 的 DOM 更新可能并未立即同步这些变化。这通常是因为 Vue 的异步更新队列导致的。

在你的原始 tagClose 方法中:

tagClose(ele) {
  const arr = this.selectData
  const res = arr.filter((item) => item.id !== ele.id)
  this.selectData = res // 直接修改数据,Vue 可能还未同步更新 DOM
},

尽管 this.selectData 被更新为一个新的数组,但 Vue 的虚拟 DOM diff 算法可能在某些情况下(特别是当涉及到复杂组件或异步更新时)未能及时反映这些变化。因此,尽管数据层面已经正确,但视图层面可能还未更新,导致你看到的页面上仍然显示旧的状态或错误的状态。

当你在 tagClose 方法中添加了 this.loadPage() 调用后:

tagClose(ele) {
  const arr = this.selectData
  const res = arr.filter((item) => item.id !== ele.id)
  this.loadPage() // 可能触发了 Vue 的重新渲染或更新检查
  this.selectData = res
},

this.loadPage() 方法可能做了某些事情(尽管你未提供 loadPage 的实现细节),这些操作可能间接地强制 Vue 框架去重新检查并更新 DOM。例如,loadPage 可能改变了某个状态(如 loadingCom),这个状态的改变触发了 Vue 的响应式系统去重新渲染相关组件。

在你的 loadingCom 方法中:

loadingCom() {
  this.loadingCom = false
  this.$nextTick(function () {
    this.loadingCom = true
  })
},

使用 this.$nextTick() 确保了在 DOM 更新完成后才改变 loadingCom 的值,这进一步强调了 Vue 的异步更新机制和确保数据变化与 DOM 更新同步的重要性。

解决方案

  • 确保在数据更新后,如果视图没有正确反映,可以尝试使用 Vue.nextTick()this.$nextTick() 来确保在 DOM 更新完成后执行后续操作。
  • 检查是否有其他可能影响 Vue 响应式更新的代码,如深度嵌套的对象或数组操作,这些可能需要使用 Vue.set() 或其他方法来确保响应式。
  • 考虑使用 Vuex 或其他状态管理库来更好地管理复杂状态更新和同步问题。
1 个回答

你遇到的问题是由于 Vue 的响应式系统没有及时检测到 selectData 数组的变化,导致页面没有正确更新。你提到使用 this.loadPage() 方法后问题解决了,这是因为你强制触发了组件的重新渲染。

解决

使用 Vue.set() 方法

tagClose(ele) {
  const arr = this.selectData;
  const res = arr.filter((item) => item.id !== ele.id);
  this.$set(this, 'selectData', res);
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题