7

我将 create-react-app 用于多语言项目。我想使用“cssJanus”或“rtlcss”之类的库将 Sass 生成的 CSS 文件转换为单独的文件,然后在切换到另一种语言时使用新生成的文件。

这是我的 index.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();

这就是我的“App.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 之间切换。

我搜索了很多类似的东西,但没有运气。

或者,如果您有更好的方法,我会全力以赴。

4

3 回答 3

7

这是一个简单的解决方案,需要弹出并添加轻量级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.css包含您的 rtl 样式的附加文件。然后我们需要告诉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

然后从您的任何组件中使用它。所以无论如何,我确定我错过了一些东西,也许这是一种糟糕的方法,但它似乎有效,这里是演示

于 2019-02-08T02:10:03.430 回答
1

如果您使用 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更容易在您的应用程序中使用。

于 2019-02-09T16:11:39.820 回答
-1

环顾四周,airbnb 有一个名为react-with-direction的库,它提供了一个 DirectionProvider - 组件,您可以根据语言将组件包装在其中。希望有帮助。

于 2019-02-01T22:50:41.450 回答