使用 @material-ui/core V4(準確地說是 4.12.3)我有一個使用 webpack 和 babel 成功創建的自定義元素。我曾經使用@material-ui/core makeStyles 來設計它。現在我正在升級到 @mui/material v5 并想使用來自 @mui/material 的內置組件,但它們不會在自定義元素中顯示樣式。請注意,我需要將此作為自定義元素,因為它將集成到另一個托管應用程式中。
index.tsx 在 v4 之前
import AppComponent from './App';
import { render } from 'react-dom';
import { StylesProvider, jssPreset } from '@material-ui/core/styles';
import { create } from 'jss';
class MyWebComponent extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: 'open' });
const mountPoint = document.createElement('custom-jss-insertion-point');
const reactRoot = shadowRoot.appendChild(mountPoint);
const jss = create({
...jssPreset(),
insertionPoint: reactRoot,
});
render(
<StylesProvider jss={jss}>
<AppComponent />
</StylesProvider>,
mountPoint
);
}
}
customElements.define('my-element', MyWebComponent);
升級到 @mui/material v5(準確地說是 v5.0.4),首先我嘗試使用 StyledEngineProvider 來安裝樣式。然后我嘗試使用@mui/styles jssPreset。無論哪種方式都行不通。我的意思是不起作用是 AppComponent 參考的 DataContainer 具有 @mui/material 組件,并且它們都在沒有任何樣式的情況下加載(例如 Grid、Button、InputLabel、Select 等等)。
首先嘗試使用 StyledEngineProvider
import AppComponent from './App';
import { ThemeProvider, createTheme, StyledEngineProvider } from '@mui/material/styles';
import { render } from 'react-dom';
const theme = createTheme();
class MyWebComponent extends HTMLElement {
connectedCallback() {
// can't use jss in mui v5
const shadowRoot = this.attachShadow({ mode: 'open' });
const mountPoint = document.createElement('custom-insertion-point');
const reactRoot = shadowRoot.appendChild(mountPoint);
render(
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<AppComponent />
</ThemeProvider>
</StyledEngineProvider>,
mountPoint //I have also used reactRoot here instead and got same result
);
}
}
customElements.define('my-element', MyWebComponent);
第二次嘗試@mui/styles jssPreset
import AppComponent from './App';
import { render } from 'react-dom';
import { StylesProvider, jssPreset } from '@mui/styles';
import { create } from 'jss';
class MyWebComponent extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: 'open' });
const mountPoint = document.getElementById('jss-insertion-point');
const reactRoot = shadowRoot.appendChild(mountPoint);
const jss = create({
...jssPreset(),
insertionPoint: reactRoot,
});
render(
<StylesProvider jss={jss}>
<AppComponent />
</StylesProvider>,
mountPoint
);
}
}
customElements.define('my-element', MyWebComponent);
應用組件
import React from 'react';
import { Suspense } from 'react';
import DataContainer from './components/DataContainer';
class AppComponent extends React.Component<any> {
render() {
return (
<Suspense fallback='Loading...'>
<div className='AppComponent'>
<DataContainer />
</div>
</Suspense>
);
}
}
export default AppComponent;
資料容器
import { styled } from '@mui/material/styles';
import Box from '@mui/material/Box';
import Paper from '@mui/material/Paper';
import Grid from '@mui/material/Grid';
import Button from '@mui/material/Button';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import FormControl from '@mui/material/FormControl';
const Item = styled(Paper)(({ theme }) => ({
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
}));
export default function FullWidthGrid() {
return (
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={2}>
<Grid item xs={6} md={8}>
<Button variant="contained">xs=6 md=8</Button>
</Grid>
<Grid item xs={6} md={4}>
<Item>xs=6 md=4</Item>
</Grid>
<Grid item xs={6} md={4}>
<Item>xs=6 md=4</Item>
</Grid>
<Grid item xs={6} md={8}>
<Item>xs=6 md=8</Item>
</Grid>
</Grid>
<div>
<FormControl sx={{ m: 1, minWidth: 180 }}>
<Select autoWidth>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Twenty</MenuItem>
<MenuItem value={21}>Twenty one</MenuItem>
<MenuItem value={22}>Twenty one and a half</MenuItem>
</Select>
</FormControl>
</div>
</Box>
);
}
索引.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="favicon.ico" />
<link rel="apple-touch-icon" href="logo192.png" />
<link rel="manifest" href="manifest.json" />
<title>React Custom Element</title>
</head>
<body>
<my-element id="elem"> </my-element>
</body>
</html>
這是我看到的:

這就是我應該在此堆疊閃電戰中看到的內容。(請注意,不幸的是,我無法使用自定義元素創建 stackblitz)

uj5u.com熱心網友回復:
這是我將如何做到的:
您需要創建style標簽。這將是情感(材料 ui 5 樣式解決方案)的入口點,以插入作用域陰影 DOM 樣式。
下一步是配置jss和情感快取
const jss = create({
...jssPreset(),
insertionPoint: reactRoot,
});
const cache = createCache({
key: 'css',
prepend: true,
container: emotionRoot,
});
最后要做的是將我們的樹包裝在提供者中
render(
<StylesProvider jss={jss}>
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>
<Demo />
</ThemeProvider>
</CacheProvider>
</StylesProvider>,
mountPoint
);
完整示例:
import React from 'react';
import Demo from './demo';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import { StylesProvider, jssPreset } from '@mui/styles';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import { create } from 'jss';
import { render } from 'react-dom';
const theme = createTheme();
class MyWebComponent extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: 'open' });
const emotionRoot = document.createElement('style');
const mountPoint = document.createElement('div');
shadowRoot.appendChild(emotionRoot);
const reactRoot = shadowRoot.appendChild(mountPoint);
const jss = create({
...jssPreset(),
insertionPoint: reactRoot,
});
const cache = createCache({
key: 'css',
prepend: true,
container: emotionRoot,
});
render(
<StylesProvider jss={jss}>
<CacheProvider value={cache}>
<ThemeProvider theme={theme}>
<Demo />
</ThemeProvider>
</CacheProvider>
</StylesProvider>,
mountPoint
);
}
}
if (!customElements.get('my-element')) {
customElements.define('my-element', MyWebComponent);
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/345881.html
