首页 > 解决方案 > 如何从@babel/template 中移除环绕 IIFE?

问题描述

我正在尝试将一些 Ember 代码转换为 React。这就是我想要改造的东西。

export default Ember.Component.extend(({
    didInsertElement() { }
});

export default class MyComponent extends React.Component {
    componentDidMount() { }
}

我编写了一个 babel 插件,并尝试Ember.Component.extend用方法生成的 AST 节点替换调用template。这是代码片段。

通天塔插件

const { default: template } = require("@babel/template");

const code = `class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let classDeclarationNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(classDeclarationNode);
            }
        }
    };
};

输出

export default (function () {
  class TestComponent extends React.Component {
    componentDidMount() {}
  }
})();

ClassDeclaration我得到的语句不是我上面写的预期代码,而是用IIFE. 有什么办法可以去掉IIFE

我已经为这个问题苦苦挣扎了一整天,但没有办法解决它。


顺便说一句,我也尝试parseExpression了方法,但仍然无法得到我想要的。

通天塔插件

const { parseExpression } = require('@babel/parser');

const code = `class TestComponent extends React.Component { 
    componentDidMount() { }
}`;
let expression = parseExpression(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            CallExpression(path) {
                if (!path.getSource().startsWith("Ember.Component.extend")) {
                    return;
                }
                path.replaceWith(expression);
            }
        }
    };
};

输出

export default (class TestComponent extends React.Component {
  componentDidMount() {}
});

它非常接近正确的代码,除了一对额外的(). 有什么办法可以生成纯的class declaration

标签: babeljsbabel-plugin

解决方案


感谢loganfsmythSlack上的帮助,问题终于解决了。我应该替换整个节点,export default但不仅是CallExpression. 这是代码。

通天塔插件

const { default: template } = require("@babel/template");

const code = `export default class TestComponent extends React.Component { 
   componentDidMount() { }
 }`;
let rootNode = template.ast(code);
module.exports = function ({ types: t }) {
    return {
        visitor: {
            ExportDefaultDeclaration(path) {
                let isMatchedNode = (path.node.declaration &&
                    t.matchesPattern(path.node.declaration.callee, "Ember.Component.extend"));
                if (!isMatchedNode) {
                    return;
                }
                path.replaceWith(rootNode);
            }
        }
    };
};

输出

export default class TestComponent extends React.Component {
  componentDidMount() {}
}


推荐阅读