vue3 为什么id是唯一,input却同时会展示?

现在我们有这样需求,对用户的聊天记录可以编辑(如下图),我也实现了这个功能,但是有个问题,就是我每次点击一条数据编辑时,点击下一条,上一条数据不会关闭,很纳闷!我这里每个meg_id都是独立的也获取到了,却每次点击都是不是我想要的效果。我想要的是点击1后,再点击2的时候1关闭,不要同时都打开,是互斥的效果。
image.png
下面具体实现过程:

子组件:

<!-- 编辑文本内容 -->
<div class="chat-container" v-if="props.dialogData.showEditContent && changeMsgId">
            <div class="chat-input-box">
              <div class="top-boxes" v-loading="contentLoading">
                <el-input ref="textInput" id="chat-input" autosize
                  v-model="editContent" type="textarea" @input="updateCursorPosition" @click="updateCursorPosition" @keyup="updateCursorPosition" :placeholder="$t('text_send_to')" />
              </div>
            </div>
            <div class="input-tips" >
              ESC键<span class="pub-color">取消</span> · 回车键<span class="pub-color">保存</span>
            </div>
          </div>
          <div v-else :class="['dc-chat-content', props.dialogData.author.bot ? 'dc-chat-bot-content' : '']">
            <!-- 工具栏渲染 -->
            <el-popover placement="right" :visible="toolsVisible" :offset="1" :show-arrow="false"
              popper-class="custom-popper" :teleported="false">
              <div v-if="!props.dialogData.checked" class="more">
                <el-button-group>
                  <el-tooltip  v-for="item in menuItems" :key="item.id" effect="dark" :content="item.title" placement="top">
                    <el-button :icon="item.icon" size="small" :disabled="item.id === '2' && (userInfo.username !== props.dialogData.author.username || !Boolean(props.dialogData.content))" @click="handleSelect(item.id)" />
                  </el-tooltip>
                </el-button-group>
              </div>
.......

script内主要代码:

const props = defineProps<DcDialogItemProps>()
const emit = defineEmits<{
  (event: 'menuClick', value: string, item: object ): void
}>()
const menuItems = [
  {
    id: '1',
    icon: 'Finished',
    title: $t('text_multiple_choice')
  },
  {
    id: '2',
    icon: 'Edit',
    title: $t('btn_edit')
  },
  {
    id: '3',
    icon: 'ChatDotSquare',
    title: $t('btn_reply')
  }
]

// 处理菜单项点击事件
const editContent = ref('')
const changeMsgId = ref('')
const currentEditing = ref(false) //用来标记表单是否正在提交
const handleSelect = (val: string) => {
  if(val === '1') {
    props.dialogData.checked = true
  } else if (val === '2') {
    console.log('--handleSelect---2', props.dialogData);
    props.dialogData.isEditing = true
    currentEditing.value = false
    editContent.value = props.dialogData.content
    changeMsgId.value = props.dialogData.msg_id
    
  }
  emit('menuClick', val, props.dialogData)
}

父组件使用:

<dcDialogItem v-for="item in messageList"
                @menu-click="handleMenuClick"
                class="pulldown-list-item"
                :key="item.msg_id"
                :dialog-data="item"
                :id="'Msg' + item.msg_id" />

messageList的数据格式:

[
    {
        "msg_id": "1276491426334769232",
        "content": "啊撒大声地",
        "checked": false
    },
    {
        "msg_id": "1276493284222701702",
        "content": "asdasdaasdsadasd",
        "checked": false
    },
    ...省略
]

script主要方法:

const handleMenuClick = (val: string, dialogData: any) => {
  if(val === '1') {
    messageList.value.forEach((item) => {
      item.checked = true
    })
    showRecords.value = true
    showReplyMsg.value = false
    dialogData.showEditContent = false
  } else if(val === '2') {
    showReplyMsg.value = false
    replyAuthor.value = ''
    showRecords.value = false
    dialogData.showEditContent = true
  } else if(val === '3') {
    showReplyMsg.value = true
    dialogData.showEditContent = false
    replyAuthor.value = dialogData.author.username
    replyContent.value = dialogData.content
  }
}

求大佬帮忙指点,哪里问题

阅读 476
avatarAI BotBETA

在你的实现中,主要问题在于handleMenuClick方法中对dialogData.showEditContent的处理方式。由于你直接在handleMenuClick中设置了dialogData.showEditContent,这会导致所有通过v-for渲染的dcDialogItem组件都会响应这个变化,因为它们都共享同一个dialogData对象(实际上是messageList中的每个元素)。

为了解决这个问题,你需要在每个dcDialogItem组件内部维护一个独立的showEditContent状态,而不是在父组件中统一控制。这样,每个消息项就可以独立地控制其编辑内容的显示状态。

修改建议

  1. 在子组件中维护showEditContent状态
    dcDialogItem组件中,添加一个showEditContent的响应式引用(ref),并在组件内部控制它。
  2. 修改handleSelect方法
    handleSelect方法中,当选择编辑时,只更新当前组件的showEditContent状态,而不是通过props传递。
  3. 移除父组件中的相关逻辑
    在父组件的handleMenuClick方法中,移除与showEditContent相关的逻辑,因为这部分现在由子组件控制。

子组件修改示例

<script setup>
import { defineProps, ref } from 'vue';

const props = defineProps<DcDialogItemProps>();
const showEditContent = ref(false); // 在子组件中维护

const handleSelect = (val: string) => {
  if (val === '2') {
    showEditContent.value = true; // 直接在子组件中设置
    // 其他逻辑...
  }
  // 发送事件到父组件
  emit('menuClick', val, props.dialogData);
};
</script>

<template>
  <div v-if="showEditContent" class="chat-container">
    <!-- 编辑内容 -->
  </div>
  <div v-else>
    <!-- 非编辑内容 -->
  </div>
</template>

父组件修改示例

<template>
  <dcDialogItem
    v-for="item in messageList"
    :key="item.msg_id"
    :dialog-data="item"
    @menu-click="handleMenuClick"
  />
</template>

<script setup>
const handleMenuClick = (val: string, dialogData: any) => {
  // 这里不再处理与编辑内容显示相关的逻辑
  // ... 其他逻辑
};
</script>

通过这种方式,每个dcDialogItem组件都可以独立控制其编辑内容的显示状态,从而解决你遇到的问题。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Microsoft
子站问答
访问
宣传栏