【问题标题】:ES6 modules and decorator patternES6 模块和装饰器模式
【发布时间】:2017-04-01 09:47:21
【问题描述】:

我了解 import 语句提供了对模块的只读绑定,我猜它取决于模块加载器,但它是否可以使用 ES6 模块导入、装饰和重新导出?

例如,使用 rollup.js 时会失败


test.plugin.js

import * as d3 from 'd3'    
d3.ui = {test: 1};    
export default d3;

index.js

import * as d3 from 'd3'
import './src/test.plugin'

汇总错误...

Illegal reassignment to import 'd3'
src\test.plugin.js (6:0)
4:
5: import * as d3 from 'd3'
6: d3.ui = {test: 1};

这也是...

test.plugin.js
export default (d3) => d3.ui = {test: 1};

index.js

import * as d3 from 'd3'
import test from './src/test.plugin'

test(d3);

第一个失败是因为导入是不可变的,第二个是因为模块解析是静态的。

是否应该可以在 ES6 模块中使用装饰器模式?

【问题讨论】:

    标签: d3.js rollup es6-modules


    【解决方案1】:

    更新

    问题是模块对象不可扩展。可扩展的是模块对象内的对象。

    模块A

    let mod = { a, b, c };
    // Once exported the "mod" object cannot be extended from the outside
    export mod;
    

    index.js

    // What you are saying here is 
    import * as mod from "moduleA.js"
    
    // mod cannot be extended here
    // mod.b can be extended though
    mod.b.ui = {test: 1};
    

    默认导出

    当您执行默认导出时,您可以扩展它,因为default 实际上是一个嵌套属性。

    模块A

    let mod = { a, b, c };
    // Once exported as default
    export default mod;
    

    index.js

     import mod from "moduleA.js"
    
     // mod is effectively a prop of the module object, so it can be extended
     mod.d = { ... };
    

    在您的情况下,您可以执行以下操作:

    test.plugin.js

    // Import d3 as a composition of props
    import * as d3 from 'd3';
    // Create a new object using the Object.assign operator
    // You can use the spread operator too
    const d3plus = Object.assign({ui: () => 'test'}, d3);
    // Now d3plus will be extendable!
    export default d3plus;
    

    index.js

    import d3plus from 'test.plugin.js';
    
    console.log(d3plus.ui);
    

    老错答案

    这是我在阅读规范时弄错了的答案。公平地说,之前some other module bundler got it wrong,作为es6模块areprettyhard

    当您拥有模块 A 并想用新功能/新事物装饰它时,您有两种选择:

    • 包装模块A,然后再使用包装器
    • 编写在需要时应用的装饰器函数(如第二个示例中所示)。

    在前一种情况下,你可以这样做:

    test.plugin.js

    import * as d3 from 'd3'    
    d3.ui = {test: 1};    
    export default d3;
    

    index.js

    // Note that using this wrapper makes sure you have the extra stuff all the time
    import d3plus from './src/test.plugin';
    
    console.log(d3plus.ui);
    

    使用第二种方法,您必须获得装饰器操作的结果:

    test.plugin.js

    export default (d3) => {
      d3.ui = {test: 1};
      // Do not forget to return the new object
      return d3;
    };
    

    index.js

    import * as d3 from 'd3'
    import pluginify from './src/test.plugin'
    
    // Note that this change is local to this module only
    const d3plus = pluginify(d3);
    console.log(d3plus.ui);
    

    您可以使用更多技巧来获得相同的结果,但我建议您明确说明您应用于模块的丰富过程。

    【讨论】:

    • 有趣...感谢您的回复。事实上,当我尝试您的第一个选项并且 chrome 抛出第二个选项时,我得到与以前相同的错误,说该对象不可扩展Can't add property ui, object is not extensible。不过我的想法和你的一样。
    • 我的错。我弄错了。我认为问题取决于所做的导出绑定的类型。我会更新答案。
    猜你喜欢
    • 2018-09-19
    • 2011-07-18
    • 2013-07-01
    • 2014-10-29
    • 2011-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-14
    相关资源
    最近更新 更多