You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在浏览器处理Web Component前将其隐藏?

如何避免带插槽的Web Component初始化时闪烁?

这个问题和“如何防止Web Component出现闪烁”类似,但存在两个关键差异:

  • 组件包含插槽内容,无法在加载完成前将innerHTML设为空
  • 不希望Web Component的JS执行阻塞页面渲染

我曾考虑用CSS先隐藏元素,等组件初始化完成后再显示,但这个CSS片段需要在所有使用组件的地方引入,既缺乏模块化还容易被遗漏。

模态框组件代码

HTML模板

<div id="BLUR" part="blur" class="display-none">
    <div id="DIALOGUE" part="dialogue">
        <div id="CLOSE" part="close">
            X
        </div>
        <slot></slot>
    </div>
</div>

JavaScript代码

const name = "wc-modal";
const template = document.getElementById("TEMPLATE_" + name);

class Component extends HTMLElement {
    static get observedAttributes() { return ["open"]; } // prettier-ignore

    constructor() {
        super();
        this.attachShadow({ mode: "open" });
        this.shadowRoot.appendChild(template.content.cloneNode(true));
    }
    connectedCallback() {
        if (this.initialised) return; // 防止元素被移动时重复初始化
        this.setupEventListners();
        this.init();
        this._upgradeProperty("open");
        this.initialised = true;
    }
    init() {}
    get(id) {
        return this.shadowRoot.getElementById(id);
    }

    _upgradeProperty(prop) {
        /*
        组件加载前设置属性会导致 setter 被值覆盖,需删除属性后重新调用 setter
        */
        if (this.hasOwnProperty(prop)) {
            let value = this[prop];
            delete this[prop];
            this[prop] = value;
        }
    }

    // 绑定事件监听
    setupEventListners() {
        this.get("CLOSE").addEventListener("click", () => this.removeAttribute("open"));
        this.get("BLUR").addEventListener("click", () => this.removeAttribute("open"));
        // 阻止对话框的点击事件冒泡到遮罩层,避免误触发关闭
        this.get("DIALOGUE").addEventListener("click", (event) => event.stopPropagation());
    }

    // 属性变更回调
    attributeChangedCallback(name, oldValue, newValue) {
        switch (name) {
            case "open":
                // open 属性为空字符串表示显示,null 表示隐藏
                if (newValue === null) this.hideModal();
                else this.showModal();
        }
    }

    // 属性 getter/setter
    get open() { return this.hasAttribute("open"); } // prettier-ignore
    set open(value) { value ? this.setAttribute("open", "") : this.removeAttribute("open"); } // prettier-ignore

    // 工具方法与事件处理器
    showModal() {
        this.get("BLUR").classList.remove("display-none");
        // 禁用背景滚动
        document.body.style.overflow = "hidden";
    }
    hideModal() {
        this.get("BLUR").classList.add("display-none");
        // 恢复背景滚动
        document.body.style.overflow = "unset";
    }
}

window.customElements.define(name, Component);

内容的提问来源于stack exchange,提问作者run_the_race

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 22:06:33