Storybook中用@lit-labs/react封装Lit组件遇adoptedStyleSheets错误求助
解决Storybook中Lit组件封装为React组件后多实例样式加载报错问题
我之前也碰到过几乎一模一样的问题!这确实是Storybook环境下特有的Lit样式加载时序/缓存类问题,哪怕ShadowDOM本身是样式封装的,但架不住Storybook的模块处理机制搞事情。
问题根源分析
你用import TextareaStyles from "./textarea.scss"的方式导入样式,在单个组件实例时没问题,但多个实例时,Storybook的模块热替换(HMR)或者重复加载机制会导致同一个SCSS模块返回的不是全新的CSSStyleSheet实例,而是一个已经被处理过的重复引用/代理对象。当第二个组件尝试把这个对象加入adoptedStyleSheets时,浏览器就会抛出类型错误。
可行的解决方案
1. 改用「原始CSS字符串 + Lit css模板」的方式加载样式
这种方式能确保每次都生成独立的StyleSheet实例,从根源避免重复引用问题:
- 先调整SCSS的导入方式,让打包工具返回原始字符串(需要配置raw-loader或对应框架的raw导入语法)
- 再用Lit的
css模板字面量包裹样式
// textarea.scss :host { padding: 0.5rem; border: 1px solid #e0e0e0; border-radius: 4px; }
// Lit组件代码 import { css, LitElement } from 'lit'; // 用?raw后缀让工具返回原始CSS字符串(Vite/Rollup/Webpack都支持这个语法) import textareaCss from './textarea.scss?raw'; class Textarea extends LitElement { static get styles() { return css`${textareaCss}`; } // ... 其他组件逻辑 }
2. 修复Storybook的Webpack配置
如果不想改组件代码,可以在Storybook配置里强制SCSS模块返回原始字符串,避免被错误处理:
在.storybook/main.js中添加SCSS的loader配置:
module.exports = { stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: ['@storybook/addon-links', '@storybook/addon-essentials'], webpackFinal: async (config) => { // 添加SCSS处理规则,优先返回原始字符串 config.module.rules.push({ test: /\.scss$/, use: ['raw-loader', 'sass-loader'], exclude: /node_modules/, }); return config; }, };
记得先安装依赖:npm install raw-loader sass-loader sass --save-dev
3. 临时Workaround:手动创建新的StyleSheet实例
如果以上两种方式都暂时没法用,可以在组件的styles getter里手动复制样式内容,生成新实例:
import TextareaStyles from "./textarea.scss"; class Textarea extends LitElement { static get styles() { // 手动创建新的StyleSheet,避免重复引用冲突 const newSheet = new CSSStyleSheet(); // 兼容不同打包工具返回的样式格式 newSheet.replaceSync(TextareaStyles.cssText || TextareaStyles); return [newSheet]; } // ... 其他组件逻辑 }
内容的提问来源于stack exchange,提问作者Kyle
相关产品推荐
相关产品推荐

