Skip to content

fix(layout): stabilize declaration types and simplify slot presence handling#374

Merged
gene9831 merged 2 commits into
opentiny:developfrom
SonyLeo:fix/layout-optimize
Jul 1, 2026
Merged

fix(layout): stabilize declaration types and simplify slot presence handling#374
gene9831 merged 2 commits into
opentiny:developfrom
SonyLeo:fix/layout-optimize

Conversation

@SonyLeo

@SonyLeo SonyLeo commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

背景

本次 PR 主要处理了 layout 组件的两个相关问题:

  1. LayoutSurface 的 props 类型定义在 .vue 内部,导致声明生成阶段出现 TS4023 / TS4058,类型名无法稳定导出。
  2. Layout 通过执行 slot、解析 VNode 来反推 header / aside / footer 是否“真的有内容”,这会让布局结构依赖 slot 的内部实现细节,不符合“显式输入决定视图结构”的组件设计路线。

(注:当前 PR 是 layout 组件 e2e 测试 - #372 的前置提交)

问题修改

1. 收敛 LayoutSurface 的类型出口

原因分析:

组件构建过程中,出现了类型问题(如下图)

image
  • Layout.vue 模板引用 LayoutSurface 后,声明生成工具会把子组件 props 类型间接带入父组件导出类型。
  • 如果这个类型定义在 .vue 私有上下文内,声明打包时就可能无法稳定命名,进而触发:
    • TS4058 Return type of exported function has or is using name ... but cannot be named
    • TS4023 Exported variable ... has or is using name ... but cannot be named

相关参考:

结论是:

  • 问题不在于 defineProps 不能引用外部类型;
  • 问题在于声明生成阶段引用了 .vue 内部私有类型名;
  • 将这类会进入导出链路的类型提升到普通 .ts 模块,是更稳定的做法。

2. 删除 slot 内容反向推断逻辑

  • 删除 utils/slots.ts
  • Layout.vue 不再执行 slot、解析 Comment / Text / Fragment / VNode 来判断区域是否“有内容”。
  • 改为只根据 slot 是否被提供来决定区域是否存在:
const hasLeftAside = computed(() => Boolean(slots['left-aside']))
const hasHeader = computed(() => Boolean(slots.header))
const hasFooter = computed(() => Boolean(slots.footer))
const hasRightAside = computed(() => Boolean(slots['right-aside']))

原因分析:

参考 #370 讨论,可以得出结论:

  • Layout 本来应该根据显式输入组织布局;
  • 不应该通过执行 slot、分析返回的 VNode 结构来反推业务状态或内容有效性;
  • 这类判断只能覆盖当前层 VNode 结构,无法可靠代表最终 DOM / 最终视觉结果;
  • 也会让组件结构依赖调用方 slot 的内部写法,导致契约变得隐式。

预期实现

Layout 的结构语义收敛为:

  • 提供了 slot,就渲染对应区域;
  • 不提供 slot,就不渲染对应区域。

测试调整

后续 #372 中:

由于 Layout 的 slot 语义已经改为“slot presence 决定结构”,对应结构测试也做了同步调整:

  • 不再验证“slot 已声明但内部内容变空时自动去壳”;
  • 改为验证“slot 声明被省略时,不保留 header / aside shell / resize trigger”。

验证

已验证:

pnpm.cmd -F @opentiny/tiny-robot build

通过。

已验证:

pnpm.cmd -F tiny-robot-test test src/layout/specs/structure.spec.ts

通过。

影响说明

行为变化

  • 旧行为:
    • slot 已声明,但内部 v-if="false" 时,Layout 可能尝试移除 header / aside shell
  • 新行为:
    • 只要 slot 被声明,Layout 就认为该区域存在
    • 如果希望区域不存在,应在 slot 声明边界控制是否提供 slot

兼容性

  • 本次修改没有新增公开 props。
  • 公开 API 基本保持不变。
  • 主要变化是 layout 的结构判断语义更直接、更稳定。

总结

  • 类型边界更清晰:避免 .vue 私有类型进入导出链路
  • 结构边界更清晰:避免通过 slot 内容反推布局结构

最终效果是:

  • layout 的类型导出更稳定;
  • layout 的结构语义更简单、更可预测;
  • layout 的使用方式更符合“显式输入决定视图结构”的组件设计原则。

Summary by CodeRabbit

  • Bug Fixes

    • Layout sections now appear based on whether slots are provided, making header, footer, and side panels behave more consistently.
    • Improved layout surface prop handling to keep component behavior aligned with the current layout state.
  • Refactor

    • Simplified internal layout slot logic and consolidated related layout typing for better maintainability.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Layout.vue's slot-emptiness computation was replaced with simple slot-presence checks (Boolean(slots[...])), removing the hasNonEmptySlotContent import; the corresponding utility function was deleted from slots.ts. LayoutSurfaceProps was relocated from an inline interface in LayoutSurface.vue into a new exported interface in internal.type.ts.

Changes

Layout refactor

Layer / File(s) Summary
Slot presence detection
packages/components/src/layout/Layout.vue, packages/components/src/layout/utils/slots.ts
Replaced hasNonEmptySlotContent content-based checks with Boolean(slots[...]) presence checks for aside/header/footer computations; removed the now-unused hasNonEmptySlotContent utility function entirely.
LayoutSurfaceProps relocation
packages/components/src/layout/internal.type.ts, packages/components/src/layout/components/LayoutSurface.vue
Added exported LayoutSurfaceProps interface to internal.type.ts; LayoutSurface.vue removes its local interface and imports the type along with related floating types from internal.type, narrowing its index.type imports to floating resize types only.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • opentiny/tiny-robot#364: Introduced the original hasNonEmptySlotContent slot-checking logic and the local LayoutSurfaceProps interface that this PR refactors.

Suggested reviewers: gene9831

Poem

A rabbit hops through slots so neat,
No more counting content, just a Boolean beat 🐇
Types now nestled in one cozy den,
internal.type.ts welcomes them in.
Hop, refactor, hop again! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: type declaration stabilization and simpler slot presence handling.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@SonyLeo SonyLeo linked an issue Jul 1, 2026 that may be closed by this pull request
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

✅ Preview build completed successfully!

Click the image above to preview.
Preview will be automatically removed when this PR is closed.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

@SonyLeo SonyLeo changed the title fix(Layout): Layout component remaining optimizations fix(layout): layout component remaining optimizations Jul 1, 2026
@SonyLeo SonyLeo changed the title fix(layout): layout component remaining optimizations fix(layout): stabilize declaration types and simplify slot presence handling Jul 1, 2026
@gene9831 gene9831 merged commit 6b17156 into opentiny:develop Jul 1, 2026
4 checks passed
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🧹 Preview Cleaned Up

The preview deployment has been removed.

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.

【优化】组件统一使用hasNonEmptySlotContent工具函数

2 participants