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

Vue.js响应式变量与变更追踪异常问题排查

解决Vue中点击消息列表重复选中、首次点击无响应的问题

问题现象

点击消息列表时,首次点击没有选中效果;第二次点击会出现两条重复的选中消息,点击次数越多,重复的内容越多。

问题根源

  1. 重复绑定监听:每次点击消息都调用SelectedItem函数,而这个函数每次执行都会给selectedMessage新增一个watch监听。点击次数越多,监听函数数量就越多,导致后续每次点击触发多次回调,出现重复选中。
  2. 循环触发watch:SelectedItem里的chooseItem函数又给selectedValue.value赋值,这会再次触发watch回调,形成无效循环,干扰正常选中逻辑。
  3. 错误的状态覆盖:下拉组件里用SelectedItem的返回值直接覆盖selectedMessage.value,但返回的是初始空值,会冲掉后续选中状态。

修复方案

1. 重构SelectedItem工具函数

修改成只绑定一次监听,移除循环赋值的逻辑:

import { watch, Ref } from "vue";

export default function SelectedItem<Type>(selectedValue: Ref<Type>, callback?: (item: Type) => void) {
  // 仅初始化一次watch监听
  watch(selectedValue, (newVal) => {
    if (newVal && callback) {
      callback(newVal);
      console.log(newVal);
    }
  });
}

2. 调整消息列表组件的调用逻辑

初始化时只调用一次SelectedItem,点击时直接更新ref值:

<template>
  <div>
    <ul>
      <li
        v-for="(message, index) in SMSMessages"
        :key="index"
        @click="selectMessage(message)"
      >
        <p>Body: {{ message.body }}</p>
        <p>Origin Number: {{ message.originNumber }}</p>
        <p>Target Number: {{ message.targetNumber }}</p>
        <p>Direction: {{ message.direction }}</p>
        <p>Message Date: {{ message.messageDt }}</p>
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
import SMSMessages from "../data/sms-messages.json";
import MessageInterface from "../Interfaces/MessageInterface";
import { ref } from "vue";
import SelectedItem from "../Interfaces/SelectedItem";

const selectedMessage = ref<MessageInterface | null>(null);

// 初始化时绑定监听,后续无需重复调用
SelectedItem(selectedMessage, (selected) => {
  // 这里可以写选中后的处理逻辑,比如同步状态到其他组件
});

const selectMessage = (message: MessageInterface) => {
  // 直接更新响应式状态,watch会自动触发回调
  selectedMessage.value = message;
};
</script>

3. 修复下拉选择组件代码

移除错误的状态覆盖,只初始化监听:

<template>
<div>
  <select v-model="selectedMessage">
    <option value="">Vyberte cílové číslo</option>
    <option
      v-for="(message, index) in SMSMessages"
      :key="index"
      :value="message.targetNumber"
    >
      {{ message.targetNumber }}
    </option>
  </select>
  <p>Vybráno: {{ selectedMessage }}</p>
</div>
</template>

<script setup lang="ts">
import SMSMessages from "../data/sms-messages.json";
import { ref } from "vue";
import SelectedItem from '../Interfaces/SelectedItem'
const selectedMessage = ref<string>("");

// 仅初始化监听即可
SelectedItem(selectedMessage, (number) => {
  console.log("选中的目标号码:", number);
});
</script>

修复后逻辑说明

  • SelectedItem现在只负责绑定一次监听,通过回调函数传递选中值,避免重复绑定和循环触发问题。
  • 所有组件在初始化时调用一次SelectedItem,后续操作直接更新响应式状态,watch自动处理后续逻辑。
  • 去掉了无效的状态覆盖,保证响应式数据正常更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 16:19:50