You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让v-list的v-model更新后再触发v-list-item的点击事件

问题:更新v-list选中项的邮件详情信息

我用Vuetify的v-list展示邮件列表,点击列表项时会拉取邮件附件等额外信息,同时希望同步更新v-model:selected绑定的selectedEmails数组,让选中的邮件包含完整的额外信息。

列表模板代码

<v-list :disabled="selectedEmailLoading" v-model:opened="open" v-model:selected="selectedEmails" select-strategy="independent" color="primary" lines="two" item-props style="height: calc(100vh - 300px);">
  <template v-for="conversation in cleanFolder">
    <v-list-item v-if="conversation.length==1" v-for="email in conversation" class="rounded-lg py-5 my-2" :value="email" @click="loadEmail(conversation[0])">
      <template v-slot:prepend="{ isActive }">
        <v-list-item-action start>
          <v-avatar color="primaryLighten1">
            <span class="text-subtitle-1">{{email.from.email_address ? getStateAbbreviation(email.from.email_address) : ""}}</span>
          </v-avatar>
        </v-list-item-action>
      </template>
      <v-list-item-title class="d-flex justify-space-between mb-1">
        <div class="d-flex align-center" style="white-space: nowrap; word-break: normal; overflow: hidden; text-overflow: ellipsis;">
          {{ email.from.email_address }}
        </div>
        <div class="d-none d-md-flex align-center pl-5">
          <v-icon v-if="email.has_attachments" icon="mdi-paperclip" size="small"></v-icon>
        </div>
      </v-list-item-title>

      <v-list-item-subtitle class="d-flex justify-space-between">
        <div class="d-flex align-center" style="white-space: nowrap; word-break: normal; overflow: hidden; text-overflow: ellipsis;">
          {{ email.subject }}
        </div>
        <div class="d-none d-md-flex align-center pl-5 text-right" style="min-width:145px">
          {{ dayjs(email.received_date).format('MM/DD/YYYY h:mm A') }}
        </div>
      </v-list-item-subtitle>
      <v-list-item-subtitle>
        <div class="mt-2" v-html="email.body_preview">
        </div>
      </v-list-item-subtitle>
    </v-list-item>
  </template>
</v-list>

点击事件函数

const loadEmail = async (email : Email) => {
  if(email.id != currentEmail.value?.id)
  {
    selectedEmailLoading.value = true    
    currentEmail.value = await emailStore.getEmail(activeMailboxLabel.value, email.id)
    // 注释部分是尝试更新选中数组的代码,但时机不对
    // selectedEmails.value = selectedEmails.value.map((selectedEmail : Email) => {
    //   if (selectedEmail.id === email.id) {
    //       return currentEmail.value;
    //   }
    //   return selectedEmail;
    // });
    selectedEmailLoading.value = false
  }
}

问题分析

点击列表项时,loadEmail函数会先执行,但v-list的selectedEmails数组更新(把当前邮件加入选中列表)是在点击事件之后的DOM更新周期里,导致注释里的map逻辑执行时,当前邮件可能还没被加入selectedEmails,或者拿的还是旧的数组状态,更新无效。

解决方法

利用Vue的nextTick等待DOM更新完成,确保selectedEmails已经同步选中状态后,再执行替换逻辑:

import { nextTick } from 'vue'

const loadEmail = async (email : Email) => {
  if(email.id != currentEmail.value?.id) {
    selectedEmailLoading.value = true    
    currentEmail.value = await emailStore.getEmail(activeMailboxLabel.value, email.id)
    
    // 等待v-list完成选中状态的更新
    await nextTick()
    // 替换选中数组里对应id的邮件为完整信息版本
    selectedEmails.value = selectedEmails.value.map((selectedEmail : Email) => {
      return selectedEmail.id === email.id ? currentEmail.value : selectedEmail
    })
    
    selectedEmailLoading.value = false
  }
}

如果需要兼容手动选中的场景,也可以额外判断当前邮件是否在selectedEmails中,不过select-strategy="independent"配置下,v-list会自动处理选中状态,一般不需要额外操作。

内容的提问来源于stack exchange,提问作者Qiuzman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:34:51