如何使用 cssinjs/jss 在 shadow root 中挂载样式

bbo*_*flo 6 google-chrome-extension material-ui jss

我正在尝试在 shadow dom 中使用https://material-ui.com/组件,并且需要一种方法将这些样式注入到 shadow dom 中。默认情况下material-ui,它使用jss在后台在页面的头部注入样式。

这甚至可能吗?任何人都可以举个例子吗?

Sha*_*ean 15

这就是我的 Web 组件的样子,它是一个呈现包含 material-ui 样式的 React 应用程序的 Web 组件。

import * as React from 'react';
import { render } from 'react-dom';
import { StylesProvider, jssPreset } from '@material-ui/styles';
import { create } from 'jss';

import { App } from '@myApp/core';

class MyWebComponent extends HTMLElement {
  connectedCallback() {
    const shadowRoot = this.attachShadow({ mode: 'open' });
    const mountPoint = document.createElement('span');
    const reactRoot = shadowRoot.appendChild(mountPoint);
    const jss = create({
      ...jssPreset(),
      insertionPoint: reactRoot
    });

    render(
      <StylesProvider jss={jss}>
        <App />
      </StylesProvider>,
      mountPoint
    );
  }
}
customElements.define('my-web-commponent', MyWebComponent);
Run Code Online (Sandbox Code Playgroud)

insertionPointon jss设置为shadow root 内的实际 react root 将告诉 jss 在该 shadow root 中插入这些样式。


小智 12

使用https://github.com/Wildhoney/ReactShadow创建 shadow dom(您也可以按照之前的答案所示手动创建),我创建了一个封装逻辑的小型 WrapperComponent。

import root from 'react-shadow';
import {jssPreset, StylesProvider} from "@material-ui/styles";
import {create} from 'jss';
import React, {useState} from "react"

const WrappedJssComponent = ({children}) => {
  const [jss, setJss] = useState(null);
  
  function setRefAndCreateJss(headRef) {
    if (headRef && !jss) {
      const createdJssWithRef = create({...jssPreset(), insertionPoint: headRef})
      setJss(createdJssWithRef)
    }
  }
  
  return (
    <root.div>
      <head>
        <style ref={setRefAndCreateJss}></style>
      </head>
      {jss &&
      <StylesProvider jss={jss}>
        {children}
      </StylesProvider>
      }
    
    </root.div>
  )
}

export default WrappedJssComponent
Run Code Online (Sandbox Code Playgroud)

然后你只需要 Wrap 你的应用程序,或者你想要隐藏在里面的应用程序部分<WrappedJssComponenent><YourComponent></YourComponent></WrappedJssComponenent>

小心,一些材料 UI 组件将无法正常工作(我遇到了一些麻烦

  • ClickAwayListener,可能是因为它使用了父dom,老实说没有调查更多。
  • Popper 以及所有尝试使用 document.body 作为容器的东西都无法访问 shadow 节点中定义的 jss。您应该在 shadow dom 内提供一个元素作为容器。

  • 这太棒了!你彻底救了我!谢谢! (2认同)