如何为Material UI Reaction添加RTL支持
我正在构建一个LTR应用程序,我想添加RTL支持。 该应用程序基于材料UI反应。 我可以将应用程序旋转到RTL,因为我使用的是CSS Flex Box,只需在正文中添加dir="rtl"即可。我还在主题中添加了direction="rtl",正如前面提到的here。
但是,并非所有内容都已更改。
以此为例: 正如您在这里看到的,我在文本元素中留下了填充。 在RTL版本中,由于所有内容都颠倒了,左侧填充在UI中没有任何效果,我的意思是必须向右填充才能显示两个元素之间的小空间:
我似乎做错了什么,因为在材料UI文档here中,此功能必须在添加此代码段后开箱即用,并将组件包装在它周围。
这是我的父组件App:
import React, { PureComponent } from "react";
import { theme } from "./styling/theme";
import Routes from "./Routes";
// Redux
import { Provider } from "react-redux";
import store from "./app/store";
import LoadingBar from "react-redux-loading-bar";
// CSS
import { MuiThemeProvider } from "@material-ui/core/styles";
// import { ThemeProvider } from "@material-ui/styles";
import { create } from "jss";
import rtl from "jss-rtl";
import JssProvider from "react-jss/lib/JssProvider";
// import { StylesProvider, jssPreset } from "@material-ui/styles";
import { createGenerateClassName, jssPreset } from "@material-ui/core/styles";
import { themeObject, colors } from "./styling/theme";
// Helpers
import get from "lodash/get";
// Configure JSS
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
const generateClassName = createGenerateClassName();
function RTL(props) {
return (
<JssProvider jss={jss} generateClassName={generateClassName}>
{
props.children
}
</JssProvider>
);
}
class App extends PureComponent {
render() {
const isRtl = get(store, "classified.language.rtl", false);
return (
<Provider store={store}>
<RTL>
<MuiThemeProvider
theme={
isRtl
? { ...theme, direction: "rtl" }
: { ...theme, direction: "ltr" }
}
>
<LoadingBar
style={{
backgroundColor: colors.primary[500],
height: themeObject.spacing.unit,
zIndex: 9999
}}
/>
<Routes />
</MuiThemeProvider>
</RTL>
</Provider>
);
}
}
export default App;
这是我的组件示例(上图所示:CLList):
import React, { Component } from "react";
import PropTypes from "prop-types";
import { withStyles } from "@material-ui/core/styles";
// Helpers
import isFunction from "lodash/isFunction";
import cloneDeep from "lodash/cloneDeep";
import styles from "./CLList.styles";
const defaultImg = "IMAGE_URL_HERE";
class CLList extends Component {
static propTypes = {
classes: PropTypes.object.isRequired,
items: PropTypes.arrayOf(
PropTypes.shape({
img: PropTypes.string,
name: PropTypes.string
})
).isRequired,
onClick: PropTypes.func
};
render() {
const { classes, items, onClick } = this.props;
return (
<ul className={classes.list}>
{items.map((item, key) => (
<li
className={classes.item}
onClick={() => isFunction(onClick) && onClick(cloneDeep(item))}
key={key}
>
<img
className={classes.image}
src={item.img || defaultImg}
alt={item.name}
title={item.name}
/>
<span className={classes.label}>{item.name}</span>
</li>
))}
</ul>
);
}
}
export default withStyles(styles)(CLList);
最后一个文件是CLList的CSS:
import { colors } from "../..";
const styles = theme => ({
list: {
display: "flex",
flexDirection: "column",
listStyle: "none",
padding: 5,
margin: 0,
"& > li:not(:last-child)": {
marginBottom: 10
}
},
item: {
flex: 1,
display: "flex",
cursor: "pointer",
"&:hover": {
backgroundColor: colors.primary[50]
}
},
image: {
flex: "0 0 15%",
maxWidth: "40px",
maxHeight: "40px"
},
label: {
flex: "1",
alignSelf: "center",
paddingLeft: 20
}
});
export default styles;
我期望标签的paddingLeft=>paddingRight。这有可能吗?这是一部开箱即用的特写吗?或者,当正文包含dir="rtl"时,我是否应该只使用RTL-CSS-JS并对所有样式对象进行换行,以自动更改样式?
我也把这两个库搞混了:
- @Material-UI/core/style
- @Material-UI/样式
我应该使用第一个还是第二个?有什么不同?
感谢您抽出时间。
编辑1:
我在CSS对象上使用了rtlCSSJS,并获得了预期的结果。但我不确定这是不是最好的方法。 CLList的CSS现在如下所示:
import rtlCSSJS from "rtl-css-js";
import { colors } from "../..";
const defaultDir = document.body.getAttribute("dir");
const styles = theme =>
defaultDir === 'rtl' ? rtlCSSJS({...CSS_HERE....}) : {...CSS_HERE....};
export default styles;
解决方案
我想我找到了我自己问题的解决方案,不过请随意添加任何增强功能或更好的解决方案。
Material UI默认使用JSS-RTL,最后一个是rtl-css-js的包装器。因此不需要在中直接使用rtl-css-js,因为Material UI可以完成此工作。
我将父App组件更改为:
import React, { PureComponent } from "react";
import Routes from "./Routes";
import RTL from "./RTL";
// Redux
import { Provider } from "react-redux";
import store from "./app/store";
import LoadingBar from "react-redux-loading-bar";
import { themeObject, colors } from "./styling/theme";
class App extends PureComponent {
render() {
return (
<Provider store={store}>
<RTL>
<>
<LoadingBar
// className="loading"
style={{
backgroundColor: colors.primary[500],
height: themeObject.spacing.unit,
zIndex: 9999
}}
/>
<Routes />
</>
</RTL>
</Provider>
);
}
}
export default App;
我添加了RTL组件,它将连接到Redux来定义具有正确方向的正确主题。我将语言数据保存在Redux中,并根据此数据定义为我的应用程序提供的主题。
这是RTL组件:
import React, { PureComponent } from "react";
import PropTypes from "prop-types";
// Redux
import { connect } from "react-redux";
// CSS
import { MuiThemeProvider, createMuiTheme } from "@material-ui/core/styles";
import { create } from "jss";
import rtl from "jss-rtl";
import JssProvider from "react-jss/lib/JssProvider";
import { createGenerateClassName, jssPreset } from "@material-ui/core/styles";
// Theme
import { themeObject } from "./styling/theme";
// Helpers
import get from "lodash/get";
// Configure JSS
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
const generateClassName = createGenerateClassName();
const G_isRtl = document.body.getAttribute("dir") === "rtl";
class RTL extends PureComponent {
static propTypes = {
children: PropTypes.oneOfType([
PropTypes.array,
PropTypes.object,
PropTypes.node
]),
language: PropTypes.object
};
render() {
const { children, language } = this.props;
const isRtl = get(language, "rtl", G_isRtl);
const theme = createMuiTheme({
...themeObject,
direction: isRtl ? "rtl" : "ltr"
});
return (
<JssProvider jss={jss} generateClassName={generateClassName}>
<MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>
</JssProvider>
);
}
}
const mapStateToProps = ({ classified }) => ({
language: classified.language
});
export default connect(mapStateToProps)(RTL);
所有子组件现在都将根据语言在RTL和LTR之间切换,我们可以只专注于一个布局,所有的反转工作都是通过此插件完成的。
我还想说,遵循官方documentation中的说明对我不起作用!我找到的大多数解决方案都基于答案here。
相关文章