[英]How can I wrap a material-ui react component to a Web Component without losing the styles?
I'm developing a wrapper to transpile React components into Web Components.我正在开发一个包装器来将 React 组件转换为 Web 组件。 What do I need to apply the styles when the components are rendered in the shadow DOM?.
当组件在 shadow DOM 中呈现时,我需要应用什么样式?。
I am trying to wrap a material-ui react component (Button) in a Web Component, however when I attach the component to the shadow DOM the styles are not applied.我试图在 Web 组件中包装一个 material-ui 反应组件(按钮),但是当我将组件附加到 shadow DOM 时,样式没有应用。
//Wrapper //包装器
import ReactDOM,{ render } from 'react-dom';
import Button from '@material-ui/core/Button';
class ButtonWrapper extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
const mountPoint = document.createElement('span');
this.attachShadow({ mode: 'open' }).appendChild(mountPoint);
ReactDOM.render(
<Button variant="contained" color="primary">
Material Button
</Button>
, mountPoint);
}
}
customElements.define('button-material-wrapper', ButtonWrapper);
//HTML //HTML
<button-material-wrapper></button-material-wrapper>
//Webpack.config //webpack.config
...
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: { presets: ['@babel/preset-env', '@babel/preset-react'] }
}
},
{
test:/\.(s*)css$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
}
....
Expected output: The material-ui button is correctly rendered预期输出:material-ui 按钮正确呈现
Actual output: The material-ui button is corectly rendered as a child node of the shadow-root but the material styles are not applied.实际输出:material-ui 按钮被正确渲染为 shadow-root 的子节点,但未应用材质样式。
In webpack, style-loader helps you to add the style to global document style.在 webpack 中,style-loader 可以帮助您将样式添加到全局文档样式中。 But web component can not access the style(including the global material style) outside shadow DOM which result in your Actual output.
但是 web 组件无法访问 shadow DOM 之外的样式(包括全局材质样式),从而导致您的实际输出。 One solution I found is to use css-to-string-loader to import the string of the scss of material component manually, and then add it to the style of current shadow DOM by hand.
我找到的一种解决方案是使用css-to-string-loader手动导入material组件的scss的字符串,然后手动将其添加到当前shadow DOM的样式中。
// Webpack.config // webpack.config
{
test: /.*\.scss$/,
use: ['css-to-string-loader', 'css-loader', 'sass-loader'],
},
// In Web Component (connectedCallback) // 在 Web 组件中 (connectedCallback)
const style = document.createElement('style');
const style.innerHTML = require('@material/xxxx.scss');
const head = document.createElement('head');
head.appendChild(style);
this.attachShadow({ mode: 'open' }).appnedChild(head)
In my opinion, it's not elegant at all, looking forward to a better solution.在我看来,它根本不优雅,期待更好的解决方案。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.