【问题标题】:How can I wrap a material-ui react component to a Web Component without losing the styles?如何在不丢失样式的情况下将 material-ui react 组件包装到 Web 组件?
【发布时间】:2020-01-07 11:21:30
【问题描述】:

我正在开发一个将 React 组件转换为 Web 组件的包装器。当组件在 shadow DOM 中呈现时,我需要应用哪些样式?

我正在尝试将 material-ui 反应组件(按钮)包装在 Web 组件中,但是当我将组件附加到影子 DOM 时,不会应用样式。

//包装器

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

<button-material-wrapper></button-material-wrapper>

//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']
                }
            ]
        }
....

预期输出: material-ui 按钮正确渲染

实际输出: material-ui 按钮被正确渲染为 shadow-root 的子节点,但不应用材质样式。

【问题讨论】:

    标签: javascript reactjs components web-component


    【解决方案1】:

    在 webpack 中,style-loader 帮助你将样式添加到全局文档样式中。但是 Web 组件无法访问 shadow DOM 之外的样式(包括全局材质样式),这会导致您的实际输出。 我找到的一种解决方案是使用css-to-string-loader手动导入材质组件的scss的字符串,然后手动添加到当前shadow DOM的样式中。

    // Webpack.config

    {
        test: /.*\.scss$/,
        use: ['css-to-string-loader', 'css-loader', 'sass-loader'],
    },
    

    //在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)
    

    在我看来,一点都不优雅,期待更好的解决方案。

    猜你喜欢
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 2021-07-18
    • 2016-06-10
    • 2019-08-05
    • 2019-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多