【问题标题】:es6 - import all named module without aliases6 - 导入所有没有别名的命名模块
【发布时间】:2016-04-07 00:58:01
【问题描述】:

我知道我们可以导入所有具有别名的命名模块,如下所示,

import * as name from "module-name";

参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

实际上,我在 A.js 中重新导出了我的模块,并且在 B.js 中继承了相同的模块。 PFB。现在,它是两级继承,所以导入命名模块没什么大不了的。但是,当我将其提升到 5 级继承(A -> B -> C -> D -> E)时,我需要导入所有文件中的所有命名模块并需要执行(重新)导出相同的操作在所有。而不是这样做,

  • 有没有其他方法可以将所有命名模块的范围复制到所有级别而不重复轮子(导入和导出)
  • 这个设计的背后是让它们遵循 Opps 概念,避免重复声明相同的模块。

A.js

import React from 'react';
import I18n from 'i18n-js';
import m1 from 'module1';
import m2 from 'module2';

export default class A extends React.Component {}

export {React, I18n, m1, m2)

B.js

import BaseComponent from './A';
import {React, I18n, m1, m2) from './A;

export default class B extends A {}

有什么方法可以导入所有没有别名的命名模块,如 import {*} from './A'(而不是 B.js 中的第二个)

【问题讨论】:

  • 1.否 2. 为什么要重新导出全局可用的模块?
  • 例如:如果我没有在 A.js 中重新导出 I18n,我不能在 B.js 中使用它。但是,我可以在 B.js 中导入这一行(从 'i18n-js' 导入 I18n;)后使用 I18n。我不想这样做。
  • “我不想这样做。” --- 因为...?
  • 我很困惑为什么你要重新出口你刚进口的东西..这没有意义!您上面关于说您不能在 B 中使用相同模块的评论似乎不正确
  • "100 个组件 * 每个最少 10 个导入 = 1000 * 2 = 最终 js 中的 2000 行。" --- 这个假设是不正确的。如果您的问题与构建生产工件及其大小有关 - 请相应地更改问题并删除所有不相关的内容。

标签: javascript reactjs


【解决方案1】:

有什么方法可以导入所有没有别名的命名模块,例如 import {*} from './A'(而不是 B.js 中的第二个)

没有。

并且重新导出的整个想法超过了您在最终 js 文件中保存“行数”所需的全部内容,如您在

因为,它会在最终的 js 文件中为每次导入添加两行。考虑如果导入的行数超过 10 行,最终的 js 中将添加 20 行。当您考虑生产时,成本太高了

没有多大意义,因为这就是 JS 缩小器的用途。

总结一下:一开始就不应该这样做:

  1. 你export只需要你导出的东西
  2. 你 import 随心所欲。
  3. 您使用 JS 缩小器来优化输出 JS 文件的大小。

【讨论】:

    【解决方案2】:

    JavaScript 解决方案:

    import * as exports from 'foo';
    Object.entries(exports).forEach(([name, exported]) => window[name] = exported);
    

    注意:导入的包装对象仍然存在。


    Node.js 解决方案:

    Object.entries(require('foo')).forEach(([name, exported]) => global[name] = exported);
    

    【讨论】:

      【解决方案3】:

      global是你在node.js中的当前作用域,类似于浏览器中的window对象,所以你可以导入到这个对象中。

      从 util 模块导入所有符号:

      import * as util from "./util";
      util.importAll(util, global);
      

      在 util.js 中:

      /**
       * Takes all functions/objects from |sourceScope|
       * and adds them to |targetScope|.
       */
      function importAll(sourceScope, targetScope) {
        for (let name in sourceScope) {
          targetScope[name] = sourceScope[name];
        }
      }
      

      ... 以及许多其他功能,例如 assert() 等,我到处都需要它们,应该是 JavaScript 语言的一部分,但还没有。但正如其他人所说,请谨慎使用。

      【讨论】:

        【解决方案4】:

        这是我做的一个疯狂的实验,它有效,但它可能在我不完全理解的方面很危险。 有人可以向我解释为什么我们不这样做吗?

        var lodash = require("lodash");
        
        function $localizeAll(name) {
            return `eval("var " + Object.getOwnPropertyNames(${name}).reduce((code, prop)=>{
                if (/^[a-zA-Z$_][a-zA-Z$_0-9]*$/.test(prop)) {
                    return code.concat(\`\${prop} = ${name}["\${prop}"]\n\`);
                } else {
                    console.warn("did not import '" + prop + "'");
                    return code;
                }
            }, []).join(", ")+";")`
        }
        
        // this will make all exports from lodash available
        eval($localizeAll("lodash"));
        
        console.log(add(indexOf([1,2,6,7,12], 6), 5)); // => 7
        

        它有点复杂,因为它在两个级别上进行评估,但它基本上迭代范围内具有给定名称的对象的所有属性,并将所有名称限定为标识符的属性绑定到该名称的标识符:

        var length = lodash["length"]
          , name = lodash["name"]
          , arguments = lodash["arguments"]
          , caller = lodash["caller"]
          , prototype = lodash["prototype"]
          , templateSettings = lodash["templateSettings"]
          , after = lodash["after"]
          , ary = lodash["ary"]
          , assign = lodash["assign"]
          , assignIn = lodash["assignIn"]
          , assignInWith = lodash["assignInWith"]
          , assignWith = lodash["assignWith"]
          , at = lodash["at"]
          , before = lodash["before"]
          , bind = lodash["bind"]
          , bindAll = lodash["bindAll"]
          , bindKey = lodash["bindKey"]
          //...
          , upperCase = lodash["upperCase"]
          , upperFirst = lodash["upperFirst"]
          , each = lodash["each"]
          , eachRight = lodash["eachRight"]
          , first = lodash["first"]
          , VERSION = lodash["VERSION"]
          , _ = lodash["_"]
          ;
        

        此列表中有一些示例说明为什么这是一个坏主意(例如,它会影响 arguments)。

        您应该可以按如下方式使用它(尽管您可能不应该像他们上面所说的那样)。

        B.js

        import BaseComponent, * as extras from './A';
        
        eval($localizeAll("extras"));
        
        export default class B extends BaseComponent {}
        

        无论如何,忍不住尝试一下;)

        【讨论】:

        • 我们不这样做是因为您不知道范围内的内容或它的来源,也不知道任何工具,例如 eslint。
        • 很棒的 hack,但如果你把它放在我的代码库中,我会让你改变它,哈哈
        【解决方案5】:

        目前,没有干净的方法可以做到这一点。 但是您可以通过以下方式解决问题:

        1) 定义别名

        import * as foo from "foo"
        

        2) 编写所有模块

        import {a,b,c,d,...} from "foo"
        

        【讨论】:

          猜你喜欢
          • 2018-07-19
          • 2017-04-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-17
          • 1970-01-01
          • 2015-05-07
          相关资源
          最近更新 更多