Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

[feat]: slotController synchronous `hostUpdated()`

未关闭
#3,103 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

评估

难度
4/5
预计耗时
3-5 天
新手友好度
55/100
Issue 类型
功能
描述清晰度
基本清楚
活跃度
冷清
技术栈
typescript
领域
frontend

调研方向

Start by locating the slotController implementation and the SlotControllerPublicAPI declaration, then trace hostConnected, #initSlotMap, the MutationObserver, and the hasSlotted(), isEmpty(), and getSlotted() methods. Implement the synchronous lifecycle described in the issue and verify initial connection, reconnection, and child mutations produce correct slot state without an async timing gap.

由索引模型根据 Issue 内容生成。

描述

Alternative approach:

synchronous hostUpdated() instead of async fallback

The current fix adds a fallback in getSlotted() to query slot elements directly when #slotRecords hasn't been populated yet. This addresses the symptom but leaves the root cause: hostConnected and #initSlotMap are async, creating a timing gap where no data source exists.

The gap also affects hasSlotted() and isEmpty(), which aren't addressed here.

Why hostConnected is async

Both hostConnected and #initSlotMap await host.updateComplete just to ensure the shadow DOM exists so they can query for elements. But Lit already provides a synchronous hook that guarantees this: hostUpdated(), which runs after every render when the DOM has been committed.

Suggested change

Make hostConnected synchronous (just sets up the MutationObserver), move record initialization to hostUpdated(), and have the MutationObserver trigger a re-render instead of calling #initSlotMap directly:

  hostConnected(): void {
    this.#mo.observe(this.host, { childList: true });
    this.#slotRecords.clear();
  }

  hostUpdated(): void {
    if (this.#slotRecords.size === 0) {
      for (let slotName of this.#slotNames.concat(Object.values(this.#deprecations))) {
        slotName ||= SlotController.default;
        const slot = this.#getSlotElement(slotName);
        if (slot) {
          this.#slotRecords.set(slotName, new SlotRecord(slot, slotName, this.host));
        }
      }
      if (this.#slotRecords.size > 0) {
        this.host.requestUpdate();
      }
    }
  }

The MutationObserver callback becomes:

#mo = new MutationObserver(() => this.host.requestUpdate());

And #initSlotMap can be removed entirely.

This also requires updating the SlotControllerPublicAPI declaration to match:

hostConnected?(): void;

Why this works

  • First render: Records empty, isEmpty() returns true (matches SSR server behavior). hostUpdated() populates records and calls requestUpdate().
  • Second render: Records exist, isEmpty()/getSlotted() read live DOM via SlotRecord getters, correct results. hostUpdated() sees records exist, no requestUpdate(), no infinite loop.
  • MutationObserver: Child changes trigger requestUpdate() → re-render → SlotRecord getters reflect new DOM state. No record rebuild needed since they query live DOM.
  • Reconnection: hostConnected clears records → next render → hostUpdated() repopulates.

What this fixes that the current PR doesn't

  • hasSlotted() and isEmpty() have the same timing gap, they also read from #slotRecords and return incorrect results before async init completes. The hostUpdated() approach fixes all three methods.
  • Eliminates the async architecture that caused the issue rather than working around it.

Trade-off

The two-render pattern on initial connection is inherent <slot> elements are created by render(), so the first render can't know about them. This was already the case with the async approach.

We can spin this off to another issue if we feel the need

Originally posted by @zeroedin in https://github.com/patternfly/patternfly-elements/issues/3093#issuecomment-4252752632

主要语言
TypeScript
星标
394
派生
107
PR 合并指标
30 天内没有已合并 PR

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

patternfly/patternfly-elements 的其他 Issue

查看 patternfly/patternfly-elements 的全部 Issue

相似的 Issue

更多 TypeScript Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。