Skip to content

Conversation

@imddc
Copy link

@imddc imddc commented Sep 14, 2025

优化了代码逻辑,初始化时不需要在 onMounted 钩子中调用

#343
在这个pr中,我做了同样的修改,但由于未同步上游,导致结构混乱,故重新提交

Summary by CodeRabbit

  • Bug Fixes
    • BubbleList styles now initialize immediately on component creation, improving initial render.
    • Styles dynamically update when max height or button icon size settings change, ensuring consistent layout.
    • Reduces visual flicker and layout shifts on first load and during prop updates, providing a smoother appearance.

@coderabbitai
Copy link

coderabbitai bot commented Sep 14, 2025

Walkthrough

The component BubbleList changed how initStyle() is invoked: removed its onMounted call and moved initialization to a watcher on props (maxHeight, btnIconSize) with immediate: true, causing initStyle() to run at creation and on subsequent prop changes.

Changes

Cohort / File(s) Summary
BubbleList initStyle invocation
packages/core/src/components/BubbleList/index.vue
Removed onMounted(() => initStyle()). Modified watch(() => [props.maxHeight, props.btnIconSize], () => initStyle(), { immediate: true }) so initStyle() runs immediately on creation and when maxHeight or btnIconSize change.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant App as Parent
  participant BL as BubbleList
  participant W as Watcher
  participant IS as initStyle()

  rect rgba(200,230,255,0.25)
  note over BL: New flow
  App->>BL: Create component
  BL->>W: Setup watch([maxHeight, btnIconSize], immediate: true)
  W->>IS: Invoke immediately on creation
  IS-->>BL: Styles initialized
  App->>BL: Update maxHeight/btnIconSize
  BL->>W: Watcher detects change
  W->>IS: Re-invoke
  IS-->>BL: Styles updated
  end
Loading
sequenceDiagram
  autonumber
  participant App as Parent
  participant BL as BubbleList
  participant OM as onMounted
  participant IS as initStyle()

  rect rgba(255,235,200,0.25)
  note over BL: Previous flow (for comparison)
  App->>BL: Create component
  BL->>OM: onMounted hook
  OM->>IS: Invoke on mount
  IS-->>BL: Styles initialized
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • HeJiaYue520
  • WengJianFei

Poem

A nibble of watch, a hop from mount,
I tap my paws and lose the count—
Immediate styles, no wait in queue,
Props change, I bounce, refresh anew.
Carrot-shaped buttons sized just right,
BubbleList gleams in morning light. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title "perf(bubble-list): better way to enable default value" references a performance change in BubbleList but is too generic to clearly summarize the actual code change in this PR, which replaces an onMounted initStyle call with a watch that runs initStyle immediately (and on prop changes). It is related to the component but does not mention initStyle, onMounted, or the watch/immediate approach, so a reviewer scanning history may not understand the primary change. Because the title is vague about the concrete implementation change, the check is inconclusive. Please make the title explicit about the implementation change; for example, use "perf(bubble-list): move initStyle from onMounted to a watch with immediate:true" or "perf(bubble-list): run initStyle immediately via watcher instead of onMounted" so the main change (initStyle behavior) is clear to reviewers.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/core/src/components/BubbleList/index.vue (1)

130-160: Guard when fewer than 2 bubbles to avoid runtime error

secondLastItem can be undefined when listBubbles.length < 2, leading to a TypeError on getBoundingClientRect().

-    const secondLastItem = listBubbles[listBubbles.length - 2];
-    const { top, bottom } = secondLastItem.getBoundingClientRect();
-    const { top: containerTop, bottom: containerBottom } =
-      scrollContainer.value!.getBoundingClientRect();
-    // 之前的最后一个是现在的第二个,判断是否可见,如果可见则自动滚动
-    const isVisible = top < containerBottom && bottom > containerTop;
-    if (isVisible) {
-      scrollToBottom();
-      stopAutoScrollToBottom.value = false;
-    }
+    if (listBubbles.length >= 2) {
+      const secondLastItem = listBubbles[listBubbles.length - 2] as HTMLElement;
+      const { top, bottom } = secondLastItem.getBoundingClientRect();
+      const { top: containerTop, bottom: containerBottom } =
+        scrollContainer.value!.getBoundingClientRect();
+      // 之前的最后一个是现在的第二个,判断是否可见,如果可见则自动滚动
+      const isVisible = top < containerBottom && bottom > containerTop;
+      if (isVisible) {
+        scrollToBottom();
+        stopAutoScrollToBottom.value = false;
+      }
+    } else {
+      // 首条或仅一条气泡时,直接保持底部对齐
+      scrollToBottom();
+      stopAutoScrollToBottom.value = false;
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e3ce64d and 8ad8f80.

📒 Files selected for processing (1)
  • packages/core/src/components/BubbleList/index.vue (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: imddc
PR: element-plus-x/Element-Plus-X#343
File: packages/core/src/components/BubbleList/index.vue:27-35
Timestamp: 2025-09-14T00:44:10.411Z
Learning: User imddc prefers minimal code modifications for bug fixes rather than comprehensive refactors, focusing on solving the immediate issue with the least amount of change to existing code.

Comment on lines 44 to 52
watch(
() => [props.maxHeight, props.btnIconSize],
() => {
initStyle();
},
{
immediate: true
}
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

SSR-safety: immediate watcher invokes DOM code during SSR; also risks global CSS var clobbering

immediate: true runs the watcher callback at setup time. In SSR that executes on the server, so initStyle() will access document and crash. Additionally, writing CSS vars on document.documentElement creates cross-instance interference.

  • Minimal fix: guard DOM access inside initStyle().
function initStyle() {
  if (typeof window === 'undefined' || typeof document === 'undefined') return;
  const root = document.documentElement;
  root.style.setProperty('--el-bubble-list-max-height', props.maxHeight || '100%');
  root.style.setProperty('--el-bubble-list-btn-size', `${props.btnIconSize}px`);
}
  • Recommended (scoped) approach: bind CSS vars on the component root instead of mutating documentElement to avoid conflicts and be SSR-friendly:
const cssVars = computed(() => ({
  '--el-bubble-list-max-height': props.maxHeight || '100%',
  '--el-bubble-list-btn-size': `${props.btnIconSize}px`,
}));

Template (on the wrapper div):

<div class="el-bubble-list-wrapper" :style="cssVars">

Please confirm whether SSR is a requirement for this library; if yes, we should at least add the DOM guard now, and consider the scoped CSS vars approach next.


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Repository root: $(pwd)"

echo "--- file exists check ---"
if [ -f packages/core/src/components/BubbleList/index.vue ]; then
  echo "FOUND: packages/core/src/components/BubbleList/index.vue"
else
  echo "MISSING: packages/core/src/components/BubbleList/index.vue"
fi

echo "--- show file (first 300 lines) ---"
sed -n '1,300p' packages/core/src/components/BubbleList/index.vue || true

echo "--- search for relevant symbols in file ---"
rg -n --hidden --no-ignore-vcs --color never "initStyle|documentElement|document\.|setProperty|immediate:\s*true|watch\(" packages/core/src/components/BubbleList/index.vue || true

echo "--- grep for initStyle definition elsewhere ---"
rg -n --hidden --no-ignore-vcs --color never "function\s+initStyle|const\s+initStyle\s*=" || true

Length of output: 8723


Fix SSR-safety: guard DOM access and avoid mutating documentElement

initStyle() writes CSS vars to document.documentElement and the watcher uses immediate: true — this runs during SSR and will throw.

  • Minimal fix: guard DOM access in initStyle():
function initStyle() {
  if (typeof window === 'undefined' || typeof document === 'undefined') return;
  const root = document.documentElement;
  root.style.setProperty('--el-bubble-list-max-height', props.maxHeight || '100%');
  root.style.setProperty('--el-bubble-list-btn-size', `${props.btnIconSize}px`);
}
  • Recommended (scoped) refactor: compute CSS vars and bind to the component root instead of mutating documentElement:
const cssVars = computed(() => ({
  '--el-bubble-list-max-height': props.maxHeight || '100%',
  '--el-bubble-list-btn-size': `${props.btnIconSize}px`,
}));

template:

<div class="el-bubble-list-wrapper" :style="cssVars">

Location: packages/core/src/components/BubbleList/index.vue — initStyle() + watch(...) (lines ~33–52).

🤖 Prompt for AI Agents
In packages/core/src/components/BubbleList/index.vue around lines 33 to 52,
initStyle() mutates document.documentElement and the watcher is immediate,
causing SSR crashes; either guard DOM access at the top of initStyle() and
return early when window or document is undefined, and then keep setting CSS
vars on document.documentElement, or better compute a scoped cssVars reactive
object from props and bind it to the component root element's style (replace
writing to document.documentElement) and remove DOM mutation in initStyle();
ensure the watcher no longer performs direct DOM writes during SSR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant