【发布时间】:2019-01-20 18:56:21
【问题描述】:
简介
我正在构建一个使用内容脚本呈现 React 组件的 Chrome 扩展程序。 React 组件是一个工具栏,其中包含供用户在浏览页面时使用的子工具。我使用 Material UI 作为我的组件库和工具栏及其所有其他子组件、弹出窗口等的样式解决方案。
什么有效
使用 div 将根 React 组件注入页面可以正常工作,“Extension”作为 mountNode。
content.js(Chrome 内容脚本)
var app = $('<div id="Extension" style="position: fixed; display: block; bottom: 0px; left: 0px; width: 100vw; height: 48px; background: grey; z-index: 99999"></div>')
app.prependTo('body');
render(<App />, document.getElementById('Extension'))
app.js(主要反应组件)
Material UI 还能够生成一个新的样式对象并将 css 样式应用于页面上的子组件。所以这一切都很好
(来源)
const styles = {
root: {
display: "block",
color: "red",
},
};
(生成)
.App-root-1 {
color: red;
display: block;
}
问题
因为我在 chrome 中使用内容脚本,所以像 Facebook 这样带有通用 css 选择器的网站会尝试覆盖 Material UI 中的样式。 css 属性也有可能从 React 工具栏泄漏到主页面中。
半途而废
我当前的解决方案是使用react-shadow 来限定 React 组件周围的样式,并使其与页面的其余部分隔离。
import React from "react";
import PropTypes from 'prop-types';
import { MuiThemeProvider, createMuiTheme } from '@material-ui/core/styles';
import { withStyles } from '@material-ui/core/styles';
import ShadowDOM from 'react-shadow';
import ToolBar from './ToolBar'
const theme = createMuiTheme({
palette: {
primary: {
main: '#ef5350',
},
type: 'light'
},
status: {
danger: 'orange',
},
});
const styles = {
root: {
display: "block",
color: "red",
},
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = { open: false }
}
render () {
const { classes } = this.props;
return (
<ShadowDOM>
<div id="Toolbox">
<MuiThemeProvider theme={theme}>
<ToolBar />
</MuiThemeProvider>
</div>
</ShadowDOM>
)
}
};
App.propTypes = {
classes: PropTypes.object,
};
export default withStyles(styles)(App)
当我这样做时,从“Material-UI”生成的主题不适用于工具栏,我只剩下默认的内联样式应用于“扩展”div(上面定义,content.js )。
主题是使用来自material-ui 包的createMuiTheme(options) 生成的:
此功能成功,主题应用使用:
<MuiThemeProvider theme={theme}>
我可以确认createMuiTheme(options) & <MuiThemeProvider/>
正在工作,因为主题生成的样式表被添加为页面<head> 标记中的最后一个标记,如图所示:
<head> tag contains MUI generated styles
我需要做什么
因为我的 React 工具栏元素在 #shadow-root 内,它无法从 MUI 生成的类中接收样式,因为它们包含在主 DOM 树中的主 <head> 标记中。我相信当 <MuiThemeProvider/> 被渲染时,它会将其提供的样式表附加到 main DOM 树的顶部,NOT #shadow-root(它们需要在哪里,以便样式在本地应用)。见下图:
MUI Stylesheets in </head>, but they need moved to #shadow-root
所以我正在寻找一种解决方案,将 Material UI 生成的样式表放在 #shadow-root 下,以便它们在我的 React 工具栏组件上应用正确的样式。
1.) 有没有办法让影子 DOM 具有 <MuiThemeProvider/> 范围,或者在类名前加上 :host 之类的前缀?
2.) 有没有办法锁定使用react-shadow 创建的#shadow-root,这样当<MuiThemeProvider/> 附加样式表时,它们会被强制附加到影子根目录?
3.) 我对 React、Javascript 和创建 Chrome 扩展程序仍然非常缺乏经验。也许我已经错过了一个非常简单的解决方案?
感谢任何帮助。
【问题讨论】:
-
@wOxxOm,感谢您的回复。大部分主题都提到了使用 iFrame 进行隔离,但我已经尝试过了。我有需要在框架边界之外显示的 UI 元素。不过,还讨论了其他主题,这可能会有所帮助。我一直在看
material-ui's CSS in JS article。可以在#shadow-root 中为 JSS Provider 设置自定义 JSS 插入点。 --- Material UI - CSS in JS -
@BradenPreston 你找到解决方案了吗?我正在努力实现同样的目标。
-
@BradenPreston 兄弟,你发现如何解决这个问题了吗?我遇到了完全相同的问题...
标签: javascript reactjs google-chrome-extension material-ui shadow-dom