React新浏览器标签页使用createPortal时styled-components样式不加载
问题原因
styled-components 默认会将自动生成的CSS样式注入到当前父页面的<head>节点中,通过window.open创建的是独立的浏览器上下文,新标签页的文档和原页面完全隔离,新页面的<head>中不存在styled-components生成的样式规则,因此挂载到新页面的元素无法匹配到对应样式。
问题现象如下:
修复方案
修改NewBrowserTab组件,在新窗口初始化完成后,将原页面的样式同步到新窗口中,修改后的代码如下:
import { useState, useRef, useEffect } from 'react' import { createPortal } from 'react-dom' export const NewBrowserTab = ({ children }) => { const [container, setContainer] = useState(null) const newWindow = useRef(null) useEffect(() => { setContainer(document.createElement('div')) }, []) useEffect(() => { if (container) { newWindow.current = window.open('', '') // 初始化新窗口完整文档结构 newWindow.current.document.open() newWindow.current.document.write('<!DOCTYPE html><html><head></head><body></body></html>') newWindow.current.document.close() // 同步原页面所有样式到新窗口 const copyStyles = () => { const newWindowHead = newWindow.current.document.head // 复制所有样式节点,包括styled-components生成的样式 document.querySelectorAll('style, link[rel="stylesheet"]').forEach(node => { newWindowHead.appendChild(node.cloneNode(true)) }) } copyStyles() newWindow.current.document.body.appendChild(container) return () => { newWindow.current.close() } } }, [container]) return container && createPortal(children, container) }
如果项目存在动态更新的样式,可以额外添加MutationObserver监听原页面的style节点变化,触发时自动同步新的样式到新窗口即可。
内容的提问来源于stack exchange,提问作者OutlawSloth
相关产品推荐
相关产品推荐

