Skip to content

[BubbleList] 清空后新增一行会报错 #438

@L1yp

Description

@L1yp

目前只在dev环境下复现,暂不明白为什么打包后就不报错了,我复制官方的demo代码到本地操作也会报错。

复现步骤:

  1. 新增2个以上对话
  2. 清空会话列表
  3. 添加会话

如果问题确认,可以提供PR修复

报错位置:https://github1s.com/element-plus-x/Element-Plus-X/blob/main/packages/core/src/components/BubbleList/index.vue#L136

相关代码:

// 组件内部触发方法,跟随打字器滚动,滚动底部
function autoScroll() {
  if (scrollContainer.value) {
    const listBubbles = scrollContainer.value!.querySelectorAll(
      '.el-bubble-content-wrapper'
    );
    const secondLastItem = listBubbles[listBubbles.length - 2];
    const { top, bottom } = secondLastItem.getBoundingClientRect();
    const { top: containerTop, bottom: containerBottom } =
      scrollContainer.value!.getBoundingClientRect();
...省略
}

当props.list的长度变化(并且长度变为1的时候就会报错, watch只判断大于0则执行,漏了length=1的情况, 调用的autoScroll方法会直接报错)

<script setup lang="ts">
import type {
  BubbleListItemProps,
  BubbleListProps
} from 'vue-element-plus-x/types/BubbleList';
import type { TypewriterProps } from 'vue-element-plus-x/types/Typewriter';

type listType = BubbleListItemProps & {
  key: number;
  role: 'user' | 'ai';
};

// 示例调用
const bubbleItems = ref<BubbleListProps<listType>['list']>(
  generateFakeItems(2)
);

function generateFakeItems(count: number): listType[] {
  const messages: listType[] = [];
  for (let i = 0; i < count; i++) {
    const role = i % 2 === 0 ? 'ai' : 'user';
    const placement = role === 'ai' ? 'start' : 'end';
    const key = i + 1;
    const content =
      role === 'ai'
        ? '💖 感谢使用 Element Plus X ! 你的支持,是我们开源的最强动力 ~'
        : `哈哈哈,让我试试`;
    const loading = false;
    const shape = 'corner';
    const variant = role === 'ai' ? 'filled' : 'outlined';
    const isMarkdown = false;
    const typing = false;
    const avatar =
      role === 'ai'
        ? 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png'
        : 'https://avatars.githubusercontent.com/u/76239030?v=4';

    messages.push({
      key,
      role,
      placement,
      content,
      loading,
      shape,
      variant,
      isMarkdown,
      typing,
      avatar,
      avatarSize: '32px'
    });
  }
  return messages;
}

const bubbleListRef = ref();
const num = ref(0);

function addMessage() {
  const i = bubbleItems.value.length;
  const isUser = !!(i % 2);
  const content = isUser
    ? '哈哈哈,让我试试'
    : '💖 感谢使用 Element Plus X ! 你的支持,是我们开源的最强动力 ~'.repeat(5);
  const shape = 'corner';
  const variant = !isUser ? 'filled' : 'outlined';
  const placement = isUser ? 'end' : 'start';
  const typing: TypewriterProps['typing'] = isUser
    ? false
    : { step: 5, suffix: '🍆', interval: 35 };
  const avatar = isUser
    ? 'https://avatars.githubusercontent.com/u/76239030?v=4'
    : 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png';
  const obj = {
    key: i,
    role: isUser ? 'user' : 'ai',
    content,
    placement,
    typing,
    avatar,
    shape,
    variant,
    avatarSize: '32px',
    isFog: !isUser
  };
  bubbleItems.value.push(obj as listType);
  // 每次添加 调用 滚动到底部 触发 自动滚动
  scrollBottom();
}

function clearMessage() {
  bubbleItems.value = [];
}

function scrollToTop() {
  bubbleListRef.value.scrollToTop();
}

function scrollBottom() {
  bubbleListRef.value.scrollToBottom();
}

function scrollToBubble() {
  bubbleListRef.value.scrollToBubble(num.value);
}

onMounted(() => {
  setTimeout(() => {
    bubbleItems.value.map(item => {
      item.loading = false;
      return item;
    });
  }, 3000);
});
</script>

<template>
  <div class="component-container">
    <div class="top-wrap">
      <div class="btn-list">
        <el-button type="primary" plain @click="addMessage">
          添加对话
        </el-button>
        <el-button type="danger" plain @click="clearMessage">
          清空对话列表
        </el-button>
        <el-button type="primary" plain @click="scrollToTop">
          滚动到顶部
        </el-button>
        <el-button type="primary" plain @click="scrollBottom">
          滚动到底部
        </el-button>
      </div>

      <div class="btn-list">
        <el-input-number
          v-model="num"
          :min="0"
          :max="10"
          controls-position="right"
        />
        <el-button type="primary" plain @click="scrollToBubble">
          滚动第{{ num }}个气泡框
        </el-button>
      </div>
    </div>

    <div class="component-1">
      <BubbleList ref="bubbleListRef" :list="bubbleItems" max-height="350px" />
    </div>
  </div>
</template>

<style scoped lang="less">
.component-container {
  padding: 12px;

  .btn-list {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
  }

  .top-wrap {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 24px;
  }
}
</style>

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions