如何在浏览器处理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
相关产品推荐
相关产品推荐

