我正在为一个多语言项目使用create-react-app。我想使用一些像"cssJanus"或"rtlcss"这样的库将 Sass 生成的 CSS 文件转换为单独的文件,然后在切换到另一种语言时使用该新生成的文件。
这是我的索引.js的样子...
import React from "react";
import ReactDOM from "react-dom";
import * as serviceWorker from "./serviceWorker";
import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from "react-redux";
import App from "./App";
import { configureStore } from "./store/configureStore";
const store = configureStore();
ReactDOM.render(
<Provider store={store}>
<Router>
<App />
</Router>
</Provider>,
document.getElementById("root")
);
serviceWorker.unregister();
这是我的"应用程序.js"的样子...
import React, { Component } from "react";
import "./App.scss";
import { Route, Switch } from "react-router-dom";
import SignIn from "./features/signin/SignIn";
class App extends Component {
render() {
return (
<>
<Switch>
<Route path="/" exact component={SignIn} />
</Switch>
</>
);
}
}
export default App;
如您所见,我使用的是"./App.scss"文件,该文件只是将一堆@import语句指向"./src/css/"目录中的另一个".scss"文件......
/* autoprefixer grid: on */
@import "css/reset";
@import "css/variables";
@import "css/global";
我需要你关于如何做到这一点的建议。如何将生成的 CSS 从 App.scss 转换为 RTL 转换为自己的.css文件,并根据全局状态的变化在它们和原始生成的 CSS 之间切换。
我搜索了很多这样的东西,但没有运气。
或者如果你有更好的方法,我全听。
这是一个简单的解决方案,需要弹出并添加轻量级webpack-rtl-plugin
。
运行后
npx create-react-app react-rtl
cd react-rtl
yarn eject
yarn add -D webpack-rtl-plugin @babel/plugin-transform-react-jsx-source
转到config/webpack.config.js
并进行一些调整:
// import the plugin
const WebpackRTLPlugin = require('webpack-rtl-plugin')
// ...
module: { ... }
plugins: [
// ...,
// use the plugin
new WebpackRTLPlugin({ diffOnly: true })
].filter(Boolean),
// ...
在此阶段, 如果您运行yarn build
并查找文件夹build/static/css
,您应该希望看到包含您的 rtl 样式的其他.rtl.css
文件.然后我们需要告诉webpack
也使用 MiniCssExtractPlugin.loader
进行开发,这样它就会通过 link
标签而不是内联样式来提供样式:
// common function to get style loaders
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && { loader: MiniCssExtractPlugin.loader }, // <-- use this
// isEnvDevelopment && require.resolve('style-loader'), <-- instead of this
不要忘记插件,哈哈:
module: { ... }
plugins: [
// ...,
// isEnvProduction && <-- comment this out
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// ...
].filter(Boolean),
从这里您终于可以获取默认样式表href
并用于插入 rtl 样式。以下是实现它的方法:
class RtlCssBundleService {
constructor() {
this.rtlApplied = false
this.rtlStyles = [];
this.ltrStyles = Array.from(
document.querySelectorAll('link[rel="stylesheet"]')
)
}
insert = () => {
if (this.rtlApplied) { return }
this.rtlApplied = true
if (this.rtlStyles.length) {
return this.rtlStyles.forEach(style => {
document.body.appendChild(style)
})
}
this.rtlStyles = this.ltrStyles.map(styleSheet => {
const link = document.createElement("link")
link.href = styleSheet.href.replace(/.css$/, '.rtl.css')
link.rel = "stylesheet"
document.body.appendChild(link)
return link
})
}
detach = () => {
this.rtlApplied = false
this.rtlStyles.forEach(style => {
document.body.removeChild(style)
})
}
toggle = () => {
return this.rtlApplied
? this.detach()
: this.insert()
}
}
const rtlStyles = new RtlCssBundleService()
export default rtlStyles
然后从您的任何组件中使用它。所以无论如何,我确定我错过了一些东西,也许这是一种糟糕的方法,但它似乎有效,这是演示
如果您使用 flexbox 和 css 网格,它们内置了 RTL 支持。 然后使用 CSS 逻辑属性进行边距、填充、边框等。 如果这还不够,则可以使用[dir="rtl"] .your-class
作为后备。
现在你没有两个单独的 css 文件要维护。
下面是一个跨浏览器margin-right
示例。
-webkit-margin-end: 25px;
margin-inline-end: 25px;
@supports (not (-webkit-margin-end: 0)) and (not (margin-inline-end: 0)) {
margin-right: 25px;
}
您可以将其包装成一个mixin
,以便于在整个应用中使用。
环顾四周,有一个名为 react-with-direction from Airbnb 的库,它提供了一个 DirectionProvider - 您可以根据语言包装组件的组件。希望有帮助。