【问题标题】:Conditional import or alternative in JavaScript (ReactJS WebApp)?JavaScript(ReactJS WebApp)中的条件导入或替代?
【发布时间】:2016-04-29 03:22:08
【问题描述】:

我正在为 ReactJS webapp 实现国际化。 如何避免加载所有语言文件?

import ru from './ru';
import en from './en';

// next lines are not important for this question from here
import locale from 'locale';
const supported = new locale.Locales(["en", "ru"])

let language = 'ru';

const acceptableLanguages = {
    ru: ru,
    en: en,
}
if (typeof window !== 'undefined') {
    const browserLanguage = window.navigator.userLanguage || window.navigator.language;
    const locales = new locale.Locales(browserLanguage)
    language = locales.best(supported).code
}

// till here

// and here i'm returning a static object, containing all language variables
const chooseLang = () => {
    return acceptableLanguages[language];
}
const lang = chooseLang();

export default lang;

【问题讨论】:

    标签: javascript web-applications internationalization ecmascript-6


    【解决方案1】:

    不幸的是,在 ES6 中没有办法动态加载模块。

    即将推出的HTML Loader Spec 将支持此功能,因此您可以使用a polyfill 来使用它。

    const chooseLang = () => System.import(`./${language}`);
    export default chooseLang;
    

    但是,这现在是基于 Promise 的,因此需要像这样调用它:

    import language from "./language";
    language.chooseLang().then(l => {
        console.log(l);
    });
    

    但请记住,该规范可能会彻底改变(或完全放弃)。

    另一种选择是不将本地化存储为 Javascript 模块,而是存储为 JSON,例如

    en.json

    { "hello_string": "Hi!" }
    

    language.js

    const chooseLang = () => {
        return fetch(`./${language}.json`)
            .then(response => response.json());
    };
    

    同样,这将是基于承诺的,因此需要这样访问:

    import language from "./language";
    language.chooseLang().then(l => {
        console.log(l.hello_string);
    });
    

    该解决方案将完全符合 ES6 标准,并且不依赖于未来可能的功能。

    【讨论】:

    • 我的情况可以编译多个包(使用 webpack),但我不知道如何有条件地排除其中一个导入,至少在编译时。有什么新想法吗?
    • @stkvtflw 如果你使用 webpack,你可以使用require('./en')
    【解决方案2】:

    看来我来晚了,但我想回答我正在使用的方法。我有一个异步组件:

    import React from 'react';
    
    export default (loader, collection) => (
      class AsyncComponent extends React.Component {
        constructor(props) {
          super(props);
          this.Component = null;
          this.state = { Component: AsyncComponent.Component };
        }
    
        componentWillMount() {
          if (!this.state.Component) {
            loader().then((Component) => {
              AsyncComponent.Component = Component;
              this.setState({ Component });
    
            });
          }
        }
    
        render() {
          if (this.state.Component) {
            return (
              <this.state.Component { ...this.props } { ...collection } />
            )
          }
    
          return null;
        }
      }
    );
    

    我们称之为:

    const page1 = asyncComponent(() => import('./page1')
      .then(module => module.default), { name: 'page1' });
    

    然后我们将它用于:

      <Route path='/page1' component= {page1}/>
    

    这将确保加载是动态完成的。

    【讨论】:

      【解决方案3】:

      看看react-loadable 包 - 如果你能以某种方式将你的语言文件封装到组件中,这可能会解决你的问题。

      【讨论】:

        猜你喜欢
        • 2018-10-27
        • 2017-09-23
        • 1970-01-01
        • 2018-04-24
        • 1970-01-01
        • 2020-05-20
        • 2019-01-20
        • 2022-07-22
        • 2021-08-16
        相关资源
        最近更新 更多