Создайте CSS-файл RTL в create-реагировать-приложение и переключаться между ними на основе изменения в состоянии - PullRequest
0 голосов
/ 01 февраля 2019

Я использую приложение create-реагировать на многоязычный проект.Я хочу использовать некоторую библиотеку, например "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();

А вот как выглядит мой "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 в другой файл" .scss "в каталоге" ./src/css/ "...

/* autoprefixer grid: on */
@import "css/reset";
@import "css/variables";
@import "css/global";

Мне нужен ваш совет о том, каксделай это.Как преобразовать сгенерированный CSS из App.scss в RTL в их собственный файл .css и переключаться между ними и исходным сгенерированным CSS на основе изменения глобального состояния.

Я много искал что-то подобноено без удачи.

Или, если у вас есть лучший подход, я весь слух.

Ответы [ 4 ]

0 голосов
/ 09 февраля 2019

Если вы используете flexbox и css grid, в них встроена поддержка RTL. Затем используйте CSS Logical Properties для полей, отступов, границ и т. Д. Если этого недостаточно, тогда вы можете использовать [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 для более удобного использования в вашем приложении.

0 голосов
/ 06 февраля 2019

Один из способов решить эту проблему - поместить сгенерированные файлы CSS в общую папку, а затем сослаться на них в заголовке вашего index.html, например:

<link rel="stylesheet" id="ltr_rtl_css" href="%PUBLIC_URL%/test_ltr.css" />

Затем динамически переключить hrefатрибут при необходимости:

  const [rtl, setRtl] = useState(false);
  useEffect(
    () => {
      const dir = rtl ? "rtl" : "ltr";
      const cssElement = document.getElementById("ltr_rtl_css");
      if (cssElement) {
        const rootUrl = process.env.PUBLIC_URL ? process.env.PUBLIC_URL : "";
        const href = rootUrl + "/test_" + dir + ".css";
        cssElement.setAttribute("href", href);
      }
      document.dir = dir;
    },
    [rtl]
  );

Для создания двух файлов CSS из файла SCSS требуется отдельный шаг в процессе сборки, а не импорт файла SCSS непосредственно в JavaScript, но я не могу представитьспособ сделать это с помощью импорта без использования другого подхода к содержимому файлов SCSS.

Вот рабочий пример, демонстрирующий это:

Edit ltr/rtl

Сюда также входит пример использования атрибута html dir для управления стилизацией с помощью одного импортируемого файла CSS, но это не соответствует вашим потребностям.

Вот некоторые ресурсы для получения информации о том, как генерировать файлы CSS:

Подходы "наблюдения", описанные в приведенных выше ссылках, могут позаботиться осоздание файла ltr.Я думаю, что, возможно, можно использовать обработку cssJanus или rtlcss для одного из подходов «watch» для создания CSS-файла rtl, но в настоящее время у меня нет опыта в том, как это сделать наилучшим образом.Возможно, вам будет достаточно просто включить создание файла rtl в процесс производственной сборки.

0 голосов
/ 08 февраля 2019

Вот простое решение, которое требует извлечения и добавления облегченного 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 

и не забывал плагин, lol:

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

Затем используйте это из любого из ваших компонентов.Так или иначе, я уверен, что я что-то пропустил и, возможно, это ужасный подход, но, похоже, он работает, и вот демо 1034 *

0 голосов
/ 02 февраля 2019

Осмотрев вокруг, есть библиотека под названием реагировать с направлением от airbnb, которая предоставляет DirectionProvider - компонент, в который вы можете обернуть свои компоненты на основе языка.Надеюсь, это поможет.

...