简体   繁体   English

如何在不丢失样式的情况下将 material-ui react 组件包装到 Web 组件?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM